Ошибки и исключения Python: список с объяснениями
Коды ошибок Python - это не числа, как в HTTP, а имена классов исключений: TypeError, KeyError, ZeroDivisionError и другие. По имени и тексту сообщения можно точно понять, что сломалось и в какой строке. В статье разобрано, как читать traceback, чем синтаксические ошибки отличаются от исключений во время работы, приведена таблица встроенных исключений с причинами, а также числовые коды errno и коды завершения программы.

Содержание статьи
Как читать сообщение об ошибке
Когда программа падает, Python печатает traceback - след вызовов от точки входа до места сбоя. Читать его удобнее снизу вверх: последняя строка содержит тип исключения и пояснение, а строки над ней показывают файл, номер строки и функцию.
def average(nums):
return sum(nums) / len(nums)
print(average([]))Traceback (most recent call last):
File "main.py", line 4, in <module>
print(average([]))
File "main.py", line 2, in average
return sum(nums) / len(nums)
~~~~~~~~~~^~~~~~~~~~~
ZeroDivisionError: division by zeroЗдесь видно, что ошибка возникла в функции average на второй строке, а вызвала ее четвертая строка модуля. Начиная с Python 3.11 интерпретатор подчеркивает знаками ~ и ^ конкретную часть выражения, которая привела к сбою. Это особенно полезно в длинных строках с несколькими операциями.
Синтаксические ошибки
Синтаксическая ошибка означает, что код нарушает правила языка, и Python не может его даже разобрать. Программа не запустится вообще: ни одна строка не выполнится, пока ошибка не исправлена. Типичные причины: пропущенное двоеточие, незакрытая скобка или кавычка, опечатка в ключевом слове.
for i in range(3)
print(i)
# SyntaxError: expected ':'В эту же группу входят IndentationError (неверный отступ, например тело цикла не сдвинуто) и TabError (в одном блоке смешаны табы и пробелы). Современные версии Python пишут понятные подсказки вроде '(' was never closed, поэтому текст сообщения стоит читать целиком. Правила отступов подробно описаны в статье про идентификаторы, комментарии и отступы.
Исключения во время выполнения
Если синтаксис верный, программа запускается, но может упасть на конкретной операции: деление на ноль, открытие несуществующего файла, обращение к отсутствующему ключу. Такие ошибки называют исключениями, их можно перехватить и обработать.
open("missing.txt")
# FileNotFoundError: [Errno 2] No such file or directory: 'missing.txt'
int("12a")
# ValueError: invalid literal for int() with base 10: '12a'
"Возраст: " + 25
# TypeError: can only concatenate str (not "int") to strОтдельно стоят логические ошибки: программа работает без исключений, но выдает неверный результат, например из-за перепутанного условия или неправильной границы range(). Python о них не сообщает, их ловят тестами и отладкой.
Таблица встроенных исключений
В таблице собраны исключения, которые встречаются чаще всего, и типичные причины их появления.
| Исключение | Когда возникает |
|---|---|
AttributeError | у объекта нет такого атрибута или метода, например None.split() |
IndexError | индекс за пределами списка, строки или кортежа |
KeyError | в словаре нет запрошенного ключа |
NameError | переменная или функция не определена, часто из-за опечатки |
UnboundLocalError | локальная переменная используется до присваивания внутри функции |
TypeError | операция применена к неподходящему типу или передано не то число аргументов |
ValueError | тип подходит, но значение недопустимо: int("abc") |
ZeroDivisionError | деление или остаток от деления на ноль |
FileNotFoundError | файл или папка не найдены |
PermissionError | нет прав на чтение, запись или удаление |
ModuleNotFoundError | модуль не установлен или имя написано с ошибкой |
ImportError | модуль найден, но нужного имени в нем нет |
RecursionError | превышена глубина рекурсии, по умолчанию около 1000 вызовов |
StopIteration | next() вызван у исчерпанного итератора |
UnicodeDecodeError | байты не удалось прочитать в указанной кодировке |
OverflowError | результат вычисления с float слишком велик |
MemoryError | программе не хватило оперативной памяти |
AssertionError | условие в операторе assert оказалось ложным |
KeyboardInterrupt | пользователь прервал программу клавишами Ctrl+C |
Полный список с описанием каждого класса приведен в разделе Built-in Exceptions официальной документации.
Иерархия исключений
Все исключения - это классы, унаследованные от BaseException. Благодаря наследованию один блок except может поймать целую группу родственных ошибок.
BaseException и Exception
Прямо от BaseException наследуются системные исключения SystemExit, KeyboardInterrupt и GeneratorExit. Обычные ошибки программы наследуются от Exception, поэтому except Exception не мешает остановить скрипт через Ctrl+C. Несколько полезных групп:
LookupErrorобъединяетIndexErrorиKeyError;ArithmeticErrorвключаетZeroDivisionErrorиOverflowError;OSErrorобъединяет ошибки файлов и сети:FileNotFoundError,PermissionError,TimeoutError,ConnectionError.
print(KeyError.__mro__)
# (<class 'KeyError'>, <class 'LookupError'>, <class 'Exception'>,
# <class 'BaseException'>, <class 'object'>)Числовые коды errno
Ближе всего к привычным кодам ошибок атрибут errno у OSError. Это номер системной ошибки, а модуль errno дает для него понятные имена: ENOENT (нет такого файла), EACCES (доступ запрещен), EEXIST (файл уже существует).
import errno
try:
open("missing.txt")
except OSError as e:
print(e.errno, errno.errorcode[e.errno]) # 2 ENOENTКод завершения программы
Когда скрипт заканчивает работу, операционная система получает код выхода. Значение 0 означает успех, любое другое число сигналит о проблеме. Если исключение не перехвачено, интерпретатор печатает traceback и завершается с кодом 1. Собственный код можно задать через sys.exit().
import sys
if len(sys.argv) < 2:
print("Укажите имя файла", file=sys.stderr)
sys.exit(2)
print("Обрабатываю", sys.argv[1])В командной строке код последней программы показывает echo $? в Linux и macOS или echo %ERRORLEVEL% в Windows. Код 2 по традиции означает неправильные аргументы, так же поступает модуль argparse.
Как перехватить ошибку
Исключение можно перехватить конструкцией try/except и решить, что делать дальше: показать понятное сообщение, повторить попытку или подставить значение по умолчанию. Перехватывайте конкретные классы, а не голый except:, иначе спрячете и настоящие баги.
def to_int(text):
try:
return int(text)
except ValueError:
print(f"Не число: {text!r}")
return 0
print(to_int("42"), to_int("4x"))Блоки else, finally и перехват нескольких типов разобраны в статье обработка исключений, а создание своих классов ошибок и raise описаны на странице собственные исключения.
Частые вопросы
Короткие ответы на вопросы о кодах ошибок и исключениях в Python.
Чем ошибка отличается от исключения?
Синтаксическая ошибка мешает запуску программы, ее нельзя перехватить в том же файле. Исключение возникает при выполнении корректного кода и обрабатывается через try/except.
Как вывести полный traceback, не останавливая программу?
Внутри блока except вызовите traceback.print_exc() из модуля traceback или используйте logging.exception(), который запишет сообщение вместе со стеком вызовов.
Почему появляется ModuleNotFoundError, если библиотека установлена?
Чаще всего пакет установлен в другой интерпретатор или виртуальное окружение. Ставьте пакеты командой python -m pip install имя тем же Python, которым запускаете скрипт.
Какой код выхода у программы с необработанным исключением?
Код 1. Успешное завершение возвращает 0, а sys.exit(n) позволяет задать любое число от 0 до 255.
Как узнать тип пойманного исключения?
Запишите except Exception as e: и выведите type(e).__name__ и e: первое даст имя класса, второе текст сообщения.