Медиаблог /

Что такое исключения в Python и как их обрабатывать

8 июля 2026

Что такое исключения в Python и как их обрабатывать

Исключение в Python — объект-ошибка, который возникает во время выполнения программы (runtime) и нарушает её нормальный поток. Если исключение не перехватить, интерпретатор выведет трассировку Traceback — многострочное сообщение с типом ошибки и цепочкой вызовов — и аварийно завершит программу.

Обработка исключений в Python — разработчик за ноутбуком с кодом

Обработка исключений в Python строится на четырёх блоках: try, except, else и finally. Оператор raise генерирует исключение явно — встроенное или пользовательское. В статье разберём синтаксис этих конструкций, иерархию встроенных типов, создание собственных классов исключений, логирование ошибок и главные антипаттерны, которых лучше избегать.

image

Не знаете, с чего ребёнку начать в IT?

Дайте попробовать разные направления: Python, веб-разработку и робототехнику

Смотреть программу

Как Python сообщает об ошибке: стек вызовов и Traceback

Аннотированный вывод Traceback Python с указателями на ключевые части

Когда интерпретатор встречает ошибку, он создаёт объект исключения и «поднимает» его по стеку вызовов — LIFO-структуре (Last In, First Out — последним вошёл, первым вышел): сначала в текущую функцию, затем в вызвавшую её, и так далее — до первого перехватчика. Если перехватчика нет, программа завершается и выводится Traceback.

Traceback читается снизу вверх: нижняя строка содержит тип исключения и описание ошибки, выше — цепочка вызовов от точки сбоя к стартовому коду. Пример: функция f1() вызывает f2(), в f2() происходит ошибка во время исполнения — TypeError. Traceback покажет f2 внизу, f1 выше. Причину ищите в самой нижней строке: именно там тип и сообщение.

Хотите освоить Python с нуля — на реальных проектах, а не сухой теории? На курсе «Программирование: Уверенный старт» школьники за 4 недели пишут Telegram-бота, создают веб-приложение и собирают устройство на Arduino (микроконтроллере) — всё онлайн, бесплатно. Узнайте подробнее на странице курса.

Полная конструкция try/except/else/finally: синтаксис

Схема выполнения блока try except else finally в Python

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

try:

# код, который может вызвать ошибку

except ValueError as e:

# перехват конкретного типа

else:

# только если ошибок не было

finally:

# выполняется при любом исходе

Разберём поведение каждого блока подробнее.

Блоки try и except: перехват и обработка ошибок

Блок try следит за кодом внутри: как только возникает нештатная ситуация, выполнение прерывается и управление переходит к первому подходящему except. Если ни один обработчик исключений не подошёл — ошибка всплывает выше по стеку.

Конструкция except ExceptionType перехватывает конкретный тип. Ключевое слово as e привязывает объект исключения к переменной — через неё доступно текстовое сообщение (str(e)) и дополнительные атрибуты. Несколько типов в одном блоке перечисляются в кортеже: except (ValueError, TypeError) as e.

Порядок блоков критичен: специфические обработчики ставятся раньше общих. Если написать except Exception до except ValueError, блок ValueError никогда не сработает — его «поглотит» более широкий.

try:

n = int(input(«Введите число: «))

result = 10 / n

print(result)

except ValueError:

print(«Нужно ввести целое число»)

except ZeroDivisionError:

print(«На ноль делить нельзя»)

Блоки else и finally: полный контроль над потоком

Блок else выполняется только если в try не возникло ни одного исключения. Он разделяет «счастливый путь» и код ошибок: что делать при успехе и что при сбое — явно разнесено, без смешивания в одном блоке.

Блок finally выполняется всегда — при ошибке, успехе, повторной генерации исключения и даже при return или break внутри try. Главный сценарий — освобождение ресурсов: закрытие файлов, соединений с базой данных, сетевых сокетов.

f = open(«data.txt»)

try:

data = f.read()

finally:

f.close() # выполнится при любом исходе

Более лаконичная альтернатива при обработке исключительных ситуаций с ресурсами — контекстный менеджер with open(«data.txt») as f: он закрывает ресурс автоматически и не позволяет «забыть» вызов close().

Встроенные исключения Python и их иерархия

В Python более 70 встроенных исключений, выстроенных в иерархию. Корень — BaseException. Перехватывать его напрямую не стоит: он включает SystemExit и KeyboardInterrupt — служебные сигналы завершения программы и нажатия Ctrl+C. Поглотив их, вы лишите программу возможности нормально завершиться.

Для пользовательского кода рекомендованная база — Exception. От неё наследуются все «программные» ошибки. Промежуточные классы группируют родственные типы:

  • ArithmeticError — родитель ZeroDivisionError и OverflowError;
  • LookupError — родитель IndexError (выход за пределы индекса) и KeyError;
  • OSError — родитель FileNotFoundError и PermissionError;
  • ImportError — родитель ModuleNotFoundError.

Иерархия исключений определяет порядок блоков except: специфические перехватчики всегда раньше общих. Если написать except LookupError перед except IndexError, второй блок никогда не сработает.

Тип исключения
Когда возникает
Пример триггера
ValueError Тип верный, значение некорректно int(«abc»)
TypeError Операция над несовместимыми типами «1» + 1
ZeroDivisionError Деление на ноль 10 / 0
IndexError Индекс за пределами списка lst[99] при len=3
KeyError Ключ отсутствует в словаре d[«missing»]
FileNotFoundError Файл не найден open(«ghost.txt»)
AttributeError Объект не имеет атрибута None.split()
ImportError Модуль не найден import nonexistent

Перехват нескольких типов исключений одновременно

Если разные ошибки требуют разной реакции — используйте несколько блоков except последовательно. Если реакция одинаковая — перечислите типы в кортеже:

try:

value = int(input(«Введите число: «))

result = 10 / value

except (ValueError, ZeroDivisionError) as e:

print(f»Ошибка ввода или деления: {e}»)

Частый антипаттерн — голый except: без указания типа. Он перехватывает всё, включая KeyboardInterrupt и SystemExit: программа не завершится по Ctrl+C, а реальные ошибки скроются за молчаливым обработчиком. Правильный вариант «поймать всё» — except Exception: он не трогает системные исключения и оставляет программе возможность нормально завершиться.

Простое правило: всегда указывайте тип в блоке except. Голый except: — антипаттерн без исключений.

Оператор raise: явная генерация и повторная передача исключений

Оператор raise в Python — визуализация выброса исключения

Оператор raise позволяет генерировать исключение явно, не дожидаясь ошибки интерпретатора. Три основных режима:

  1. raise ValueError(«Значение не может быть отрицательным») — встроенное исключение; применяется для валидации входных данных.
  2. raise CustomError(«Сообщение») — пользовательское исключение с контекстом приложения.
  3. raise без аргументов внутри except — повторный вызов исключения (re-raise); traceback сохраняется и передаётся выше по стеку.

def divide(a, b):

if b == 0:

Ребенок хочет изучать программирование? Пусть начнёт с реальных проектов

На курсе школьники создают Telegram-бота, сайт и веб-приложение

  • Бесплатно — 0 ₽ за обучение
  • Портфолио — 4 готовых проекта
  • 7–11 классы — Онлайн, с нуля
Оставить заявку
image

raise ZeroDivisionError(«Делитель не может быть нулём»)

return a / b

Re-raise применяется в паттерне «залогировать и передать выше»: сначала logging.error(e), затем голый raise. Вышестоящий обработчик получит полный Traceback — и запись в лог, и оригинальную цепочку вызовов.

Создание собственных исключений: классы с контекстом ошибки

Иерархия пользовательских классов исключений в Python

Пользовательское исключение — обычный класс Python, унаследованный от Exception или одного из его подклассов. Наследование от классов исключений — единственный способ создать собственный тип. Минимальный синтаксис:

class NegativeValueError(Exception):

«»»Вызывается при передаче отрицательного значения.»»»

pass

Соглашения именования: суффикс Error или Exception; докстринг с описанием условий возникновения. Для передачи контекстной информации переопределите __init__:

class InsufficientFundsError(Exception):

def __init__(self, requested, available):

super().__init__(

f»Нужно {requested} ₽, доступно {available} ₽»

)

self.requested = requested

self.available = available

Преимущества: семантическая ясность и иерархическая обработка. Создайте базовый AppError, от него унаследуйте DatabaseError, ValidationError, NetworkError — и перехватывайте их как по отдельности, так и через общий базовый класс. Читаемость кода и удобство отладки при этом заметно растут.

Логирование ошибок и контекстный менеджер: профессиональный подход

Уровни логирования Python от DEBUG до CRITICAL с пояснениями

Модуль logging из стандартной библиотеки Python — правильный инструмент для записи ошибок. В отличие от print, он сохраняет временну́ю метку, уровень важности и контекст; записи уходят в файл и не теряются при перезапуске программы.

import logging

logging.basicConfig(

filename=»app.log»,

level=logging.ERROR,

format=»%(asctime)s %(levelname)s %(message)s»

)

try:

result = 10 / 0

except ZeroDivisionError as e:

logging.error(«Ошибка деления: %s», e)

Модуль поддерживает пять уровней важности: DEBUG (детали отладки), INFO (ход работы), WARNING (предупреждение), ERROR (ошибка выполнения), CRITICAL (критический сбой). Используйте уровень, соответствующий серьёзности события — логирование исключений через logging.error даёт куда больше информации, чем голый print.

Для освобождения ресурсов применяйте контекстный менеджер with: он автоматически вызывает __exit__ и закрывает файл или соединение при любом исходе. Лаконичнее и надёжнее, чем паттерн try/finally + close() вручную.

Правила надёжной обработки: что делать и чего избегать

Лучшие практики обработки исключений Python — разработчик за кодом

❌ Антипаттерн
✅ Правильно
Последствие
except: без типа except Exception Перехватывает KeyboardInterrupt, блокирует Ctrl+C
except Exception: pass logging.error(…) Ошибка замалчивается, отладка невозможна
try/except в каждой функции Обработка там, где есть контекст Код засоряется, ошибки подавляются неосознанно

Оператор pass в блоке except — молчаливое игнорирование ошибок: программа продолжает работу в неизвестном состоянии. Это затрудняет отладку и делает поведение кода непредсказуемым. Если не можете полностью восстановиться после сбоя — залогируйте и передайте исключение выше через голый raise.

Отказоустойчивый код в Python строится на принципеEAFP («Easier to Ask Forgiveness than Permission» — «проще просить прощения, чем разрешения»): при редких ошибках try/except производительнее предварительных проверок через if/else. Условие if выполняется каждый раз, блок except — только при фактическом исключении. Именно поэтому грамотная обработка исключений в Python считается нормой, а не оборонительной мерой.

Часто задаваемые вопросы

Чем обработка исключений через try/except лучше проверок if/else?

Python исповедует принцип EAFP — «проще просить прощения, чем разрешения». try/except отделяет основную логику от кода ошибок и не смешивает их в одном потоке. При редких сбоях это производительнее: условие if проверяется при каждом выполнении, блок except активируется только при фактическом исключении.

Что означает «Traceback (most recent call last)» и как читать трейсбек?

Это заголовок трассировки Python. Трейсбек читается снизу вверх: нижняя строка — тип и сообщение ошибки, выше — цепочка вызовов от точки сбоя к стартовому коду. Причину ищите в самой нижней строке — не в первых.

Когда использовать finally, а когда — контекстный менеджер with?

Для одиночных ресурсов — файла или соединения с базой данных — предпочтительнее with: лаконичнее и надёжнее. finally нужен, когда требуется сложная очистка нескольких разнородных ресурсов или логика, выходящая за рамки протокола __enter__/__exit__.

Что делает raise без аргументов внутри блока except?

Повторно генерирует перехваченное исключение, сохраняя оригинальный traceback. Применяется в паттерне «залогировать и передать выше»: сначала logging.error(e), затем голый raise — ошибка дойдёт до вышестоящего обработчика с полным контекстом.

Нужно ли оборачивать каждую функцию в try/except?

Нет — это загромождает код и создаёт ложное ощущение безопасности. Исключение обрабатывают там, где есть контекст для осмысленного решения: показать сообщение, выбрать запасное значение, повторить запрос. В «транзитных» функциях лучше дать ошибке всплыть выше по стеку вызовов.

Почему нельзя перехватывать BaseException вместо Exception?

BaseException — корень всей иерархии, включая SystemExit и KeyboardInterrupt. Его перехват блокирует Ctrl+C и sys.exit() — программа не завершится по запросу пользователя или операционной системы. Используйте только Exception и его подклассы.

Как создать собственное исключение с дополнительными данными об ошибке?

Унаследуйте класс от Exception и определите __init__ с нужными полями:

class InsufficientFundsError(Exception):

def __init__(self, requested, available):

super().__init__(f»Нужно {requested}, доступно {available}»)

Добавьте докстринг и следуйте соглашению с суффиксом Error в имени класса.

Чем ValueError отличается от TypeError?

TypeError — операция применена к объекту несовместимого типа: например, сложение числа и строки (1 + «a»). ValueError — тип правильный, но значение некорректно: int(«abc») — строка передана верно, но преобразовать её в число невозможно. Первый — ошибка интерфейса, второй — ошибка данных.

Пусть ребёнок сделает первый IT-проект уже в этом месяце

Бесплатный онлайн-курс с понятной программой, поддержкой и проектами для портфолио

  • Онлайн
  • 4 недели
  • Бесплатно
  • Школьникам 7–11 классов
Подать заявку
icon