Гид по технологиям

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

5 min read Python Обновлено 01 Jan 2026
Обработка исключений в Python — руководство
Обработка исключений в Python — руководство

Рука печатает на ПК; рядом книга по Python

Зачем читать это руководство

Кто это нужно: разработчикам, техлидам и тестировщикам, работающим с Python. Цель: научить правильно обрабатывать ошибки, чтобы код был надёжным, понятным и удобным для пользователей.

Как работает обработка исключений в Python

Исключение — это сигнал о том, что какая-то часть кода не смогла выполниться. Когда возникает исключение, выполнение текущего блока прерывается и интерпретатор ищет соответствующий обработчик.

Краткое определение: исключение — объект, указывающий на ошибочную ситуацию во время выполнения программы.

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

Основные конструкции: try, except, else, finally

Простейшая форма:

try:
    # код, который может вызвать исключение
    result = 10 / x
except ZeroDivisionError:
    print("Деление на ноль запрещено")

Блок else выполняется, если исключение не произошло:

try:
    total = a + b
except NameError:
    print("Переменные не определены")
else:
    print("Сумма вычислена:", total)

Блок finally выполняется всегда и полезен для очистки ресурсов:

try:
    f = open('data.txt')
    data = f.read()
except IOError as e:
    print('Ошибка ввода/вывода:', e)
finally:
    if 'f' in locals():
        f.close()

Совет: используйте менеджеры контекста (with) вместо finally для работы с ресурсами, когда это возможно.

Ловите конкретные исключения, не используйте bare except

Нельзя оставлять голый except:

try:
    do_work()
except:
    pass  # плохая практика: скрывает ошибки

Лучше явно указать тип исключения:

try:
    do_work()
except ValueError as e:
    logger.error('Неверное значение: %s', e)
    raise

Важно: если вы не можете обработать исключение локально — логируйте контекст и пробрасывайте дальше (raise), чтобы не потерять причину ошибки.

Исключения с несколькими except и объединённый перехват

Можно перехватывать разные исключения отдельно или группировать их в кортеже:

try:
    x = int(user_input)
    y = 10 / x
except (ValueError, TypeError) as parse_err:
    print('Неверный ввод:', parse_err)
except ZeroDivisionError as zde:
    print('Деление на ноль')

Искусство сообщения об ошибках: контекст и читаемость

Хорошее сообщение об ошибке должно:

  • кратко объяснять, что пошло не так;
  • указывать, где это произошло (контекст);
  • предлагать действие пользователю, если возможно.

Пример:

except FileNotFoundError as e:
    raise RuntimeError('Не удалось загрузить конфигурацию. Проверьте путь: {}'.format(config_path)) from e

Оператор “from” сохраняет цепочку исключений (exception chaining) и помогает при отладке.

Пользовательские исключения

Иногда стандартных исключений недостаточно. Тогда определяют свои классы исключений, унаследованные от Exception.

Пример простого пользовательского исключения:

class AppError(Exception):
    """Базовое исключение приложения"""
    pass

class ValidationError(AppError):
    def __init__(self, field, message):
        self.field = field
        self.message = message
    def __str__(self):
        return f"Ошибка в поле {self.field}: {self.message}"

# Использование
try:
    raise ValidationError('email', 'некорректный формат')
except ValidationError as e:
    print(e)

Правило: пользовательские исключения должны нести смысловую нагрузку и быть легко идентифицируемыми.

Примеры распространённых ошибок и как их обрабатывать

  • NameError: доступ к несуществующей переменной — проверяйте входные данные или объявляйте значения по умолчанию.
  • ValueError/TypeError: неверный тип/значение — проверяйте предусловия функции и ввод.
  • ZeroDivisionError: проверяйте делитель до операции.
  • IOError/FileNotFoundError: используйте проверки наличия файла или менеджер контекста.

Практический приём: валидируйте внешние данные на входе и выбрасывайте понятные ValidationError вместо того, чтобы позволять цепочке исключений ломаться глубже по стеку.

Альтернативы обработке исключений

  • Явная валидация и возврат кодов ошибок. Полезно в низкоуровневом коде или там, где исключения дорогие по производительности.
  • Использование типов результата, например, возвращать Optional/Union[Result, Error] (в Python — соглашение с None или объектом-результатом).

Когда не использовать исключения:

  • для обычного контроля потока (исключения должны быть для экстраординарных ситуаций);
  • в горячем коде, где исключение вызывается часто и оказывает существенную нагрузку.

Мини-методология: как внедрять обработку исключений в проект

  1. Определите базовое приложение-исключение (AppError) и семейство дочерних исключений (ValidationError, ExternalServiceError и т.д.).
  2. Внешний API/слой приложения ловит AppError и преобразует их в понятные сообщения для пользователя/клиента.
  3. Внутри библиотек — ловите и пробрасывайте (raise from) с контекстом.
  4. Логируйте ошибки с достаточной информацией (адрес, входные данные, состояние), но не записывайте чувствительные данные.
  5. Покрывайте критические пути тестами и имитируйте ошибки внешних сервисов.

Чеклист по ролям

Разработчик:

  • ловить конкретные исключения;
  • не подавлять исключения без логирования;
  • использовать raise from при перепаковке ошибок.

Тестировщик:

  • писать тесты на ожидаемые исключения;
  • имитировать недоступность внешних сервисов.

Техлид/архитектор:

  • определить схему пользовательских исключений;
  • стандартизировать формат сообщений и уровни логирования.

Шпаргалка: часто используемые шаблоны

  • Перехват и логирование с повторным выбросом:
try:
    risky()
except Exception as e:
    logger.exception('Ошибка при выполнении risky')
    raise
  • Перехват с замещением сообщения и сохранением причины:
try:
    parse_config()
except (ValueError, KeyError) as e:
    raise RuntimeError('Ошибка парсинга конфигурации') from e
  • Менеджер контекста вместо finally:
with open('file.txt') as f:
    data = f.read()

Модели принятия решений и эвристики

  • Эвристика 1: если ошибка вызвана внешним вводом — валидируйте и выбрасывайте ValidationError.
  • Эвристика 2: если ошибка может быть восстановлена локально — обрабатывайте её; если нет — пробрасывайте.
  • Эвристика 3: в публичном API возвращайте контролируемые ошибки/коды, не дампьте стектрейсы пользователю.

Когда обработка исключений терпит неудачу — типичные кейсы

  • Подавление исключений (pass) скрывает реальные проблемы и усложняет отладку.
  • Ловля Exception без повторного выброса может привести к неконсистентному состоянию программы.
  • Логирование чувствительных данных (паролей, токенов) при ошибках — риск для безопасности.

Риски и mitigations

  • Риск: потеря трассировки ошибки. Митигирование: использовать raise from и логирование с exception().
  • Риск: утечка ресурсов. Митигирование: менеджеры контекста и тесты.
  • Риск: раскрытие внутренних деталей пользователю. Митигирование: маскировать детали и возвращать понятные сообщения.

Критерии приёмки

  • Все критические пути имеют тесты, проверяющие ожидаемую обработку ошибок.
  • Нельзя иметь bare except в кодовой базе без явного комментария и проверки.
  • Все пользовательские исключения документированы и содержат понятные сообщения.

Примеры тест-кейсов и приёмки

  • Ввод неправильного формата приводит к ValidationError и корректному сообщению пользователю.
  • Отсутствие файла приводит к FileNotFoundError, который преобразуется в понятную ошибку уровня приложения.
  • При недоступности внешнего сервиса генерируется ExternalServiceError и лог с таймстемпом.

Краткая галерея крайних случаев

  • Исключения, которые нужно игнорировать: временные оповещения в фоне, где повторная попытка ожидаема.
  • Исключения, которые нужно немедленно фиксировать: нарушения целостности данных, потеря связи с базой.

1‑строчный глоссарий

  • Исключение: объект об ошибке во время выполнения.
  • raise: оператор для возбуждения исключения.
  • try/except: блок для обработки исключений.
  • raise from: связывает новое исключение с исходным.

Резюме

Обработка исключений — не просто способ скрыть ошибки. Это инструмент коммуникации с пользователем и способом поддержания надёжности системы. Ловите конкретные исключения, логируйте контекст, используйте пользовательские классы для доменной семантики и избегайте подавления ошибок без следа.

Важно: протестируйте сценарии ошибок, документируйте формат исключений и всегда думайте о безопасности при логировании.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Переход с Microsoft Office на WPS Office
Офисное ПО

Переход с Microsoft Office на WPS Office

Как изменить цвет текста с помощью CSS
Веб-разработка

Как изменить цвет текста с помощью CSS

CSS тени: box-shadow и text-shadow
CSS

CSS тени: box-shadow и text-shadow

Как встроить MP3 на сайт — HTML5, Google Drive, CMS
Веб

Как встроить MP3 на сайт — HTML5, Google Drive, CMS

Начать сайт с HTML5 Boilerplate — быстрое руководство
Веб-разработка

Начать сайт с HTML5 Boilerplate — быстрое руководство

Как обновиться до Windows 10 Mobile
Мобильные ОС

Как обновиться до Windows 10 Mobile