Python try: except: finally - программирование

Python try: except: finally

# Open new file to write
file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    file.write("Hello World!")
    file.close()

Вышеприведенный код разорван из функции. Одна из пользовательских систем сообщает об ошибке в строке:

file.write("Hello World!")

Ошибка:

AttributeError: 'NoneType' object has no attribute 'write'

Вопрос: если python не смог открыть данный файл, выполняется блок "except", и он должен return, но управление переходит к строке, которая бросает заданную ошибку. Значение переменной "file" равно "None".

Любые указатели?

4b9b3361

Ответ 1

Вам не следует записывать файл в блок finally, поскольку любые исключения, поднятые там, не будут улавливаться блоком except.

except bock выполняется, если есть исключение, вызванное блоком try. Блок finally всегда выполняет все, что происходит.

Также не должно быть необходимости инициализировать переменную file до none.

Использование return в блоке except не пропускает блок finally. По самой своей природе он не может быть пропущен, поэтому вы хотите разместить там свой "очищающий" код (т.е. Закрывать файлы).

Итак, если вы хотите использовать try: except: finally, вы должны делать что-то вроде этого:

try:
    f = open("file", "w")
    try:
        f.write('Hello World!')
    finally:
        f.close()
except IOError:
    print 'oops!'

Более простой способ сделать это - использовать оператор with:

try:
    with open("output", "w") as outfile:
        outfile.write('Hello World')
except IOError:
    print 'oops!'

Ответ 2

Если файл не открывается, строка file = open(filePath, 'w') завершается с ошибкой, поэтому для file ничего не назначается.

Затем выполняется предложение except, но ничего не находится в файле, поэтому file.close() завершается с ошибкой.

Предложение finally всегда выполняется, даже если есть исключение. И поскольку file по-прежнему отсутствует, вы получаете другое исключение.

Вы хотите использовать else вместо finally для вещей, которые происходят только в случае отсутствия исключения.

    try:
        file = open(filePath, 'w')
    except IOError:
        msg = "Unable to create file on disk."
        return
    else:
        file.write("Hello World!")
        file.close()

Почему else? Документы Python говорят:

Использование предложения else лучше, чем добавление дополнительного кода в предложение try, поскольку оно позволяет избежать случайного обнаружения исключения, которое не было вызвано защищенным кодом инструкцией try... except.

Другими словами, это не вызовет IOError из вызовов write или close. Это хорошо, потому что тогда разум не был "Невозможно создать файл на диске". - это была бы другая ошибка, из-за которой ваш код не был подготовлен. Это хорошая идея не пытаться обрабатывать такие ошибки.

Ответ 3

какова логика включения

file.write("Hello World!")

внутри предложения finally?? я думаю, что это должно быть помещено в try предложение.

try:
        file = open(filePath, 'w')
        file.write("Hello World!")
except IOError:
        print("Unable to create file on disk.")
finally:
        file.close()

Ответ 4

за исключением того, что не выполняется (поскольку тип - IOError), это, наконец, часть, которая выдает еще одну ошибку типа AttributeError, потому что file = None.

Ответ 5

Вы можете сделать что-то вроде этого:

try:
    do_some_stuff()
finally:
    cleanup_stuff()

Ответ 6

Вот самое прямое решение вашей проблемы. Я использую идиому проверки file_obj != None в блоке finally.

Кстати, вы должны знать, что file - это имя класса Python, поэтому вы должны выбрать другое имя переменной.

file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    if file != None:
        file.write("Hello World!")
        file.close()

Ответ 7

наконец, всегда вызывается в конце, даже если исключение происходит. Вы можете использовать это, чтобы убедиться, что открытые ресурсы закрыты (например, соединение с БД, файл и т.д.).

Я думаю, вы неправильно поняли семантику.

Ваша логика должна быть в "try", вы должны иметь дело с исключениями в блоке "except", а "finally" выполняется независимо от того, как ваш метод завершается, используйте его для очистки.

Ответ 8

Всегда желательно написать вашу логику или код, которые могут генерировать исключение в блоке try и использовать блок finally для закрытия ресурсов.