2.25. Обработка ошибок¶
Большинство ошибок времени выполнения в Python проявляются как исключения – именованный, структурированный способ сообщить, что что-то пошло не так. ValueError, TypeError, KeyError, OSError, MemoryError – всё это примеры; каждое из них является классом, и возбуждение исключения останавливает текущий вызов и ищет обработчик в окружающем коде.
2.25.1. try / except¶
Оберните блок кода в try, чтобы перехватить любое возбуждаемое им исключение:
try:
n = int(input_text)
except ValueError:
n = 0
Если преобразование int(...) завершается неудачей, управление переходит к блоку except вместо дальнейшего распространения ошибки. Если input_text был корректной строкой с целым числом, блок except пропускается.
Один try может иметь несколько блоков except, каждый из которых перехватывает свой вид ошибки:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python сопоставляет их по порядку; первый, чей класс исключения подходит, обрабатывает проблему. Перехват Exception (базового класса почти для всего) обрабатывает любую ошибку; оставьте это для самого внешнего уровня программы, где альтернатива – аварийное завершение.
Предупреждение
Пустой except: (без класса после ключевого слова) также перехватывает KeyboardInterrupt – исключение, которое IDE отправляет, когда вы нажимаете кнопку stop, чтобы прервать выполняющийся скрипт. Цикл, обёрнутый в пустой except: pass, проглотит прерывание и продолжит работу, не оставив никакого способа остановить скрипт, кроме перезагрузки питания.
Предпочитайте except Exception: пустому except:, когда вам действительно нужно перехватывать широко. KeyboardInterrupt наследуется от BaseException, а не от Exception, поэтому except Exception: оставляет кнопку остановки рабочей.
2.25.1.1. Исследование исключения¶
Чтобы прочитать сообщение, прикреплённое к исключению, назовите его с помощью as:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
Переменная, связанная через as, действительна только внутри блока except.
2.25.2. else и finally¶
У блока try есть два необязательных дополнения.
else выполняется только тогда, когда try завершился без возбуждения исключения:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
Помещение того, «что делать, когда сработало», в else сохраняет блок try узким – в try должна попадать только строка, которая может завершиться неудачей.
finally выполняется в конце в любом случае – независимо от того, удался ли try, возбудил исключение, которое было обработано, или возбудил исключение, которое вот-вот распространится дальше:
try:
do_work()
finally:
cleanup()
finally выполняется всегда. else выполняется только на пути без исключения.¶
Для большинства шаблонов захвата/освобождения предпочитайте менеджер контекста паре try / finally – сам ресурс управляет своей очисткой.
2.25.3. Распространённые встроенные исключения¶
Краткий список исключений, с которыми вы будете часто сталкиваться:
ValueError– правильный тип, неправильное значение (bytes([300])– 300 имеет правильный тип, но выходит за допустимый диапазон байта 0..255).TypeError– совершенно неправильный тип (len(42)).IndexError– индекс за пределами конца последовательности.AttributeError– обращение к атрибуту, который не существует ("abc".foo).OSError– сбой файловой системы или ввода-вывода.MemoryError– закончилась куча. На среде выполнения с ограниченной памятью это может происходить во время нормальной работы – а не только в патологических случаях.