Обработка исключений в Python
Иногда, во время работы программы случаются непредвиденные ситуации. Например, попытка поделить число на ноль или чтение несуществующего файла вызовут ошибку и остановят выполнение программы. Такие ситуации в программировании называют исключительными ситуациями, а ошибки — исключениями (exception). Для разных ситуаций есть свои типы исключений:
2 / 0 # ZeroDivisionError: division by zero open('non_existing_file.txt') # FileNotFoundError: No such file or directory
Как вы могли заметить, названия исключений довольно точно описывают причину возникновения ошибки. Это часть плана: исключения нужны для того, чтобы рассказать программисту что произошло. Однако, когда выбрасывается исключение, вместе с его типом на экран выводится ещё целая куча сопутствующей информации. Давайте рассмотрим такой пример:
# Файл example.py def average(numbers): return sum(numbers) / len(numbers) average([1, 2, 3]) # Вернёт 2 average([]) # Сделает ба-бах!
Traceback (most recent call last): # 6 File "example.py", line 5, in # 5 average([]) # 4 File "example.py", line 2, in average # 3 return sum(numbers) / len(numbers) # 2 ZeroDivisionError: division by zero # 1
Простыня текста на последних шести строчках называется трэйсбэком. Он выглядит страшно, но читать его — полезно. В нём Python рассказывает что же случилось.
Важно: трейсбек читают снизу вверх. Именно поэтому мы расставили такую нумерацию строчек в примере.
Давайте разберём каждую строчку в примере выше:
1) ZeroDivisionError: division by zero — тип исключения и сообщение с причиной ошибки. Если перевести на русский, сразу понятно: ОшибкаДеленияНаНоль: вы поделили на ноль.
2) return sum(numbers) / len(numbers) — строка, на которой произошла ошибка.
3) File «example.py», line 2, in average — где эту строку искать. В файле example.py , на второй строке, в функции average .
4 и 5) Начиная с этой строки и далее, Python будет указывать какие строки кода исполнялись до момента, с которого началась вся цепочка. Эта информация нужна, когда ошибка произошла где-то внутри чужого кода. Просматривая трейсбэк снизу вверх, можно найти строчку вашего кода, которая стала причиной ошибки.
6) Начало трейсбэка
Каким бы длинным трейсбек ни был, в большинстве случаев вам понадобится только последние две-три строки. Как правило, их достаточно, чтобы определить что и где произошло. Выходит, трейсбэки не такие уж и страшные, если знать, где искать.
Как перехватить ошибку
Если возникшее исключение — часть плана или вы хотите обработать его особенном образом, то на такой случай в Python существует конструкция try-except :
filepath = user.get_avatar_filepath() try: avatar = Image.open(filepath) except FileNotFoundError: avatar = default_avatar
Внутри блока try (внутри — это с отступами) пишется код, который потенциально может вызвать ошибку. Если исключения не произойдёт, то Python проигнорирует блок except и пойдёт дальше. Если же возникла ошибка — сработает код внутри блока except .
Обратите внимание, что после except стоит тип исключения, который может случиться внутри try . Это правило хорошего тона. Мы явно указываем тип ошибки, которую ожидаем.
Код, в котором не указан тип ошибки выглядит так:
filepath = user.get_avatar_filepath() try: avatar = use_avatar(filepath) except: avatar = default_avatar
Однажды может случится страшное: другая ошибка. Но код будет себя вести так, будто ничего страшного не произошло, будто он просто не нашёл файл. Python не покажет трейсбек и чинить код придется методом ненаучного тыка.
Когда разработчик не указывает тип исключения, кажется, будто он просто написал такой плохой код, что сам себе не доверяет. Без особой необходимости так делать нельзя.
Что ещё почитать
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.
Исключения в python. Конструкция try — except для обработки исключений
Исключения (exceptions) — ещё один тип данных в python. Исключения необходимы для того, чтобы сообщать программисту об ошибках.
Самый простейший пример исключения — деление на ноль:
Разберём это сообщение подробнее: интерпретатор нам сообщает о том, что он поймал исключение и напечатал информацию (Traceback (most recent call last)).
Далее имя файла (File «»). Имя пустое, потому что мы находимся в интерактивном режиме, строка в файле (line 1);
Выражение, в котором произошла ошибка (100 / 0).
Название исключения (ZeroDivisionError) и краткое описание исключения (division by zero).
Разумеется, возможны и другие исключения:
В этих двух примерах генерируются исключения TypeError и ValueError соответственно. Подсказки дают нам полную информацию о том, где порождено исключение, и с чем оно связано.
Рассмотрим иерархию встроенных в python исключений, хотя иногда вам могут встретиться и другие, так как программисты могут создавать собственные исключения. Данный список актуален для python 3.3, в более ранних версиях есть незначительные изменения.
- BaseException — базовое исключение, от которого берут начало все остальные.
- SystemExit — исключение, порождаемое функцией sys.exit при выходе из программы.
- KeyboardInterrupt — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
- GeneratorExit — порождается при вызове метода close объекта generator.
- Exception — а вот тут уже заканчиваются полностью системные исключения (которые лучше не трогать) и начинаются обыкновенные, с которыми можно работать.
- StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов.
- ArithmeticError — арифметическая ошибка.
- FloatingPointError — порождается при неудачном выполнении операции с плавающей запятой. На практике встречается нечасто.
- OverflowError — возникает, когда результат арифметической операции слишком велик для представления. Не появляется при обычной работе с целыми числами (так как python поддерживает длинные числа), но может возникать в некоторых других случаях.
- ZeroDivisionError — деление на ноль.
- IndexError — индекс не входит в диапазон элементов.
- KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
- UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
- BlockingIOError
- ChildProcessError — неудача при операции с дочерним процессом.
- ConnectionError — базовый класс для исключений, связанных с подключениями.
- BrokenPipeError
- ConnectionAbortedError
- ConnectionRefusedError
- ConnectionResetError
- IndentationError — неправильные отступы.
- TabError — смешивание в отступах табуляции и пробелов.
- UnicodeEncodeError — исключение, связанное с кодированием unicode.
- UnicodeDecodeError — исключение, связанное с декодированием unicode.
- UnicodeTranslateError — исключение, связанное с переводом unicode.
Теперь, зная, когда и при каких обстоятельствах могут возникнуть исключения, мы можем их обрабатывать. Для обработки исключений используется конструкция try — except.
Первый пример применения этой конструкции:
Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что-то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.
Для вставки кода на Python в комментарий заключайте его в теги