Исключения (Exceptions) Python

Исключения (exceptions) — ещё один тип данных в python. Исключения необходимы для того, чтобы сообщать программисту об ошибках. Самый простой пример исключения — деление на ноль. Если попробовать запустить такую программу

z = 100 / 0

она завершится с ошибкой

Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero

ZeroDivisionError — это название исключения, а division by zero — его краткое описание. Также Python сообщит номер строки, где это исключение возникло.

Разумеется, возможны и другие исключения. Например, при попытке сложить строку и число

z = 2 + '1'

произойдет исключение TypeError

Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

В этом примере генерируется исключение TypeError. Подсказки дают нам полную информацию о том, где порождено исключение, и с чем оно связано.

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

  • BaseException — базовое исключение, от которого берут начало все остальные.
  • SystemExit — исключение, порождаемое функцией sys.exit при выходе из программы.
  • KeyboardInterrupt — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
  • GeneratorExit — порождается при вызове метода close объекта generator.
  • Exception — а вот тут уже заканчиваются полностью системные исключения (их лучше не трогать) и начинаются обыкновенные, с которыми можно работать.
  • StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов.
  • ArithmeticError — арифметическая ошибка.
  • FloatingPointError — порождается при неудачном выполнении операции с плавающей запятой. На практике встречается нечасто.
  • OverflowError — возникает, когда результат арифметической операции слишком велик для представления. Не появляется при обычной работе с целыми числами (так как python поддерживает длинные числа), но может возникать в некоторых других случаях.
  • ZeroDivisionError — деление на ноль.
  • AssertionError — выражение в функции assert ложно.
  • AttributeError — объект не имеет данного атрибута (значения или метода).
  • BufferError — операция, связанная с буфером, не может быть выполнена.
  • EOFError — функция наткнулась на конец файла и не смогла прочитать то, что хотела.
  • ImportErrorс — не удалось импортирование модуля или его атрибута.
  • LookupError — некорректный индекс или ключ.
  • IndexError — индекс не входит в диапазон элементов.
  • KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
  • MemoryError — недостаточно памяти.
  • NameError — не найдено переменной с таким именем.
  • UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
  • OSError — ошибка, связанная с системой.
  • BlockingIOError
  • ChildProcessError — неудача при операции с дочерним процессом.
  • ConnectionError — базовый класс для исключений, связанных с подключениями.
  • BrokenPipeError
  • ConnectionAbortedError
  • ConnectionRefusedError
  • ConnectionResetError
  • FileExistsError — попытка создания файла или директории, которая уже существует.
  • FileNotFoundError — файл или директория не существует.
  • InterruptedError — системный вызов прерван входящим сигналом.
  • IsADirectoryError — ожидался файл, но это директория.
  • NotADirectoryError — ожидалась директория, но это файл.
  • PermissionError — не хватает прав доступа.
  • ProcessLookupError — указанного процесса не существует.
  • TimeoutError — закончилось время ожидания.
  • ReferenceError — попытка доступа к атрибуту со слабой ссылкой.
  • RuntimeError — возникает, когда исключение не попадает ни под одну из других категорий.
  • NotImplementedError — возникает, когда абстрактные методы класса требуют переопределения в дочерних классах.
  • SyntaxError — синтаксическая ошибка.
  • IndentationError — неправильные отступы.
  • TabError — смешивание в отступах табуляции и пробелов.
  • SystemError — внутренняя ошибка.
  • TypeError — операция применена к объекту несоответствующего типа.
  • ValueError — функция получает аргумент правильного типа, но некорректного значения.
  • UnicodeError — ошибка, связанная с кодированием / раскодированием unicode в строках.
  • UnicodeEncodeError — исключение, связанное с кодированием unicode.
  • UnicodeDecodeError — исключение, связанное с декодированием unicode.
  • UnicodeTranslateError — исключение, связанное с переводом unicode.
  • Warning — Базовый класс для исключений-предупреждений. Данное семейство исключений представляет собой различные категории предупреждений.
  • BYTESWARNING — Предупреждения, связанные с возможными проблемами при работе с байтами. Данная категория предупреждений используется в случаях возможных ошибок при работе с бйтами (bytes и bytearray).
  • DeprecationWarning — Категория предупреждений о функциональности нежелательной к использованию. Эту категорию обычно используют для указания на то, что некая часть функциональности морально устарела (возможно ей на смену пришла более совершенная) и не рекомендуется к использованию.
  • FUTUREWARNING — Категория, описывающая предупреждения об изменениях в будущем. Предупреждения данной категории призваны оповещать о грядущих семантических изменениях. Пример предупреждения о грядущих изменениях из numpy:FutureWarning: comparison to 'None' will result in an elementwise object comparison in the future.
  • IMPORTWARNING — предупреждение о вероятной ошибке при импорте модуля. Предупреждения данной категории могут использоваться, например, в случаях внесения изменений в систему импорта при помощи перехватчиков (хуков).
  • PendingDeprecationWarning — Категория предупреждений о функциональности, которая вскоре должна стать нежелательной к использованию.
  • ResourceWarning — Предупреждения, связанные с возможными проблемами при работе с ресурсами. Примером использования данной категории предупреждений можут служить указание на необходимость закрытия сокета, что необходимо для высвобождения ресурсов.
  • RuntimeWarning — Предупреждение о сомнительном поведении во время исполнения. Категория может быть использована для обозначения сомнительного поведения приложения, например, если код выявил вероятные погрешности в вычислениях.
  • SyntaxWarning — Предупреждение об использовании сомнительных синтаксических конструкций. Категория используется в случаях, когда замечены вероятные синтаксические ошибки.
  • UnicodeWarning — Предупреждения, связанные с возможными проблемами при работе с Юникод.
  • USERWARNING— Класс для пользовательских предупреждений. Может использоваться пользователями в качестве базового класса для создания собственных иерархий предупреждений.

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

Первый пример применения этой конструкции:

try:
    k = 1 / 0
except ZeroDivisionError:
    k = 0
print(k)
0

В блоке try мы выполняем инструкцию, которая может породить исключение, а в блоке except мы перехватываем их. При этом перехватываются как само исключение, так и его потомки. Например, перехватывая ArithmeticError, мы также перехватываем FloatingPointError, OverflowError и ZeroDivisionError.

try:
    k = 1 / 0
except ArithmeticError:
    k = 0
print(k)
0

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

Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что‑то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.

f = open('1.txt')
ints = []
try:
    for line in f:
        ints.append(int(line))
except ValueError:
    print('Это не число. Выходим.')
except Exception:
    print('Это что ещё такое?')
else:
    print('Всё хорошо.')
finally:
    f.close()
    print('Я закрыл файл.')
    # Именно в таком порядке: try, группа except, затем else, и только потом finally.
Это не число. Выходим.
Я закрыл файл.