Подтвердить что ты не робот

Назначение else и, наконец, обработка исключений

Являются ли разделы обработки else и finally избыточности исключений? Например, существует ли разница между следующими двумя фрагментами кода?

try:
    foo = open("foo.txt")
except IOError:
    print("error")
else:
    print(foo.read())
finally:
    print("finished")

и

try:
    foo = open("foo.txt")
    print(foo.read())
except IOError:
    print("error")
print("finished")

В общем случае, нельзя ли содержимое else всегда перемещаться в try и не может ли содержимое finally просто перемещаться за пределы блока try/catch? Если да, то какова цель else и finally? Это просто для повышения удобочитаемости?

4b9b3361

Ответ 1

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

Из лошадиный рот:

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

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

официальная фраза:

Если в предложении try возникло исключение и не было обработано предложением except (или оно произошло в предложении except или else), оно повторно поднимается после finally. Предложение finally также выполняется "на выходе", когда любое другое предложение оператора try остается с помощью инструкции break, continue или return.


* Это конкретное использование было несколько устранено менеджерами контекста (with...as blocks).

Ответ 2

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

Ответ 3

Независимо от того, что происходит, выполняется блок в finally всегда. Даже если исключение не было обработано или сами обработчики исключений генерируют новые исключения.

Ответ 4

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

print(foo.read())

в вашем примере выбрасывает IOError, ваш первый фрагмент кода не поймает эту ошибку, в то время как ваш второй фрагмент будет. Вы стараетесь держать блоки try как можно меньше в общем, чтобы действительно улавливать только те исключения, которые вы хотите поймать.

Блок finally всегда выполняется, несмотря ни на что. Если, например, блок try содержит оператор return, блок finally все равно будет выполнен, а любой код под всем блоком try/except не будет.