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".
Любые указатели?
Ответы
Ответ 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 для закрытия ресурсов.