Сообщить об ошибке.

Тонкости работы конструкции try/except/else/finally в Python

Подробный алгоритм обработки исключений со всеми нюансами

Для лучшего понимания этого раздела, рекомендуем ознакомиться с общими приемами обработки исключений и использованием инструкции finally.

В конструкция try/except/else/finally определяется обработчики исключений и/или код очистки для группы операторов.

Поведение инструкции except.

В инструкциях except указывается один или несколько обработчиков исключений. Если в коде между инструкциями try/except не возникает исключения, то обработчик исключений не выполняется. При возникновении исключения в коде между инструкциями try/except запускается поиск обработчика исключения. Этот поиск проверяет выражения во всех инструкциях except по очереди, пока не будет найден тот, который соответствует исключению.

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

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err: # содержит выражение OSError as err
    print("OS error: {0}".format(err))
except ValueError: # содержит выражение ValueError
    print("Не удалось преобразовать данные в целое число.")
except: # инструкция 'except' без выражения
    print("Непредвиденная ошибка:", sys.exc_info()[0])

Для инструкций except с выражением - выражение оценивается и сравнивается с брошенным исключением в коде, между инструкцией try и первым except. Выражение соответствует исключению в том случае, если результирующий объект выражения "совместим" с исключением. Объект выражения совместим с исключением, если это класс или базовый класс объекта исключения или кортеж, содержащий элемент, совместимый с исключением.

try:
...
except (OSError, ValueError):
# инструкция 'except' содержит 
# кортеж возможных исключений
...

Если исключению не соответствует выражению, указанному в инструкции except, то поиск обработчика исключения продолжается в окружающем коде и в стеке вызовов.

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

Если найдено соответствующее выражение в инструкции except, то исключение назначается целевому объекту, указанному после ключевого слова as в этом выражении, если конечно as присутствует, далее выполняется блок кода выбранной инструкции except. Все инструкции except должны иметь исполняемый блок кода. Когда достигается конец выбранного блока, выполнение кода продолжается после выполнения всей инструкции try. Это означает, что если существуют два вложенных обработчика для одного и того же исключения и исключение возникает в предложении try внутреннего обработчика, то внешний обработчик не будет обрабатывать исключение.

Когда исключение было назначено с помощью выражения as target, то переменная target очищается в конце предложения except. Это как если бы:

except E as N:
    foo

был переведен на:

except E as N:
    try:
        foo
    finally:
        del N

Следовательно, если надо сослаться на исключение target после инструкции except, то необходимо исключению в target присвоить другой переменной. Исключения очищаются, так как с присоединенной к ним обратной трассировкой они образуют ссылочный цикл с кадром стека, сохраняя все локальные объекты в этом кадре живыми до следующей сборки мусора.

Перед выполнением блока кода инструкции except, сведения об исключении сохраняются в модуле sys и могут быть доступны через sys.exc_info(). Метод sys.exc_info() возвращает тройной кортеж, состоящий из класса исключения, экземпляра исключения и объекта трассировки, идентифицирующего точку в программе, где произошло исключение. Значение метода sys.exc_info() восстанавливаются до своих предыдущих значений (до вызова) при возврате из функции, которая обработала исключение.

Поведение необязательной инструкции else.

Необязательная инструкция else выполняется, только если поток управления покидает блок кода между try/except, не вызвав исключения и если не было выполнено ни одного оператора return, continue или break в этом блоке кода.

Исключения в блоке кода else не обрабатываются предыдущими инструкциями except.

Поведение необязательной инструкции finally.

Если в конструкции try присутствует инструкция finally, то она определяет обработчик 'cleanup'. Оператор try выполняет все инструкции, включая except и else. Если исключение возникает в любой из этих инструкции и не обрабатывается, то исключение временно сохраняется. При исполнении инструкции finally, если существует сохраненное исключение, оно повторно вызывается после выполнения блока кода инструкции finally. Если finally вызывает другое исключение, то сохраненное исключение устанавливается как контекст нового исключения. Если инструкция finally выполняет оператор return, break или continue, то сохраненное исключение отбрасывается:

def f():
    try:
        1/0
    finally:
        return 42

>>> f()
# 42

Информация об исключении недоступна программе во время выполнения инструкции finally.

Когда операторы return, break или continue выполняется в блоке кода инструкции try конструкции try/finally, блок кода инструкции finally также выполняется ‘на выходе.’

Возвращаемое значение функции определяется последним выполненным оператором return. Поскольку инструкция finally выполняется в любом случае, оператор return, выполняемый в блоке кода инструкции finally, всегда будет последним выполненным:

def foo():
    try:
        return 'try'
    finally:
        return 'finally'

>>> foo()
# 'finally'

Дополнительную информацию об исключениях можно найти в материалах "Ошибки выполнения программы" и "Обработка исключений в Python", а информацию об использовании инструкции raise генерации исключений можно найти в материале "Инструкция raise в Python"