Назначение 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
? Это просто для повышения удобочитаемости?
Ответы
Ответ 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
не будет.