Найти в Дзене

Исключения в Python: Полное Руководство

Оглавление

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

Основные типы исключений

Каждое исключение в Python — это объект класса, унаследованного от BaseException. Часто используемые типы:

1. NameError

Возникает при обращении к необъявленной переменной.

print(unknown_var) # NameError: name 'unknown_var' is not defined

2. ValueError

Некорректное значение объекта (например, попытка преобразовать строку в число, если она не является числом).

int("hello") # ValueError: invalid literal for int() with base 10: 'hello'

3. TypeError

Операция применена к объекту неверного типа.

"5" + 5 # TypeError: can only concatenate str (not "int") to str

4. SyntaxError

Ошибка синтаксиса (например, незакрытая скобка).

if True # SyntaxError: expected ':'

5. OSError

Ошибки ввода-вывода или системные сбои (например, файл не найден).

open("missing_file.txt") # FileNotFoundError (подкласс OSError)

6. RuntimeError

Общая ошибка, не попадающая под другие категории.

raise RuntimeError("Что-то пошло не так!")

7. Exception

Базовый класс для всех пользовательских исключений.

Вызов исключений

Исключения можно вызывать вручную с помощью `raise`:

if age < 0:
raise ValueError("Возраст не может быть отрицательным!")

Обработка исключений: try-except-else-finally

Конструкция `try` позволяет перехватывать и обрабатывать ошибки:

try:
....result = 10 / 0
except ZeroDivisionError:
....print("Делить на ноль нельзя!")
except (TypeError, ValueError) as e:
....print(f"Ошибка типа или значения: {e}")
else:
....print("Ошибок не было!") # Выполняется, если исключений нет
finally:
....print("Это выполнится всегда!") # Для очистки ресурсов (например, закрыть файл)

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

Создавайте свои классы исключений, наследуясь от `Exception`:

class MyCustomError(Exception):
....def __init__(self, message):
........super().__init__(message)
........self.custom_data = "Дополнительная информация"
try:
....raise MyCustomError("Кастомная ошибка!")
except MyCustomError as e:
....print(e) # Кастомная ошибка!
....print(e.custom_data) # Дополнительная информация

BaseException vs Exception

- BaseException — корневой класс для всех исключений.

Его не рекомендуется перехватывать (кроме специфических случаев), так как его подклассы включают системные ошибки (например, KeyboardInterrupt, SystemExit).

- Exception — базовый класс для обычных ошибок, которые нужно обрабатывать.

try:
....raise KeyboardInterrupt
except Exception:
....print("Этот блок не сработает, так как KeyboardInterrupt — подкласс BaseException!")

Assert для проверки условий

Инструкция assert генерирует AssertionError, если условие ложно:

def divide(a, b):
....assert b != 0, "Делитель не может быть нулём!"
....return a / b
divide(10, 0) # AssertionError: Делитель не может быть нулём!

Важно: assert не заменяет полноценные проверки — он отключается при запуске Python с флагом `-O` (оптимизация).

Получение информации об исключении

Используйте модуль traceback для вывода деталей ошибки:

import traceback
try:
....10 / 0
except:
....print(traceback.format_exc()) # Выводит полный traceback в виде строки

Цепочки исключений (Exception Chaining)

При повторном вызове исключения в блоке `except` можно сохранить оригинальную ошибку:

1. Неявная цепочка (автоматически сохраняет контекст):

try:
....10 / 0
except ZeroDivisionError:
....raise ValueError("Новая ошибка") # В сообщении будет указан оригинальный ZeroDivisionError

2. Явная цепочка (с помощью from):

try:
....10 / 0
except ZeroDivisionError as e:
....raise ValueError("Новая ошибка") from e # Указывает прямую причину

Когда что использовать?

- try-except — для обработки ожидаемых ошибок (например, ввод пользователя).

- try-finally — для гарантированного выполнения кода (закрытие файлов, соединений).

- Пользовательские исключения — для точной классификации ошибок вашего приложения.

- assert — для отладки и проверки внутренних условий.

Заключение

Исключения в Python — мощный инструмент для создания надёжного и предсказуемого кода.

- Используйте конкретные типы исключений в except.

- Не игнорируйте ошибки (например, пустой except: — это антипаттерн!).

- Создавайте понятные пользовательские исключения для улучшения читаемости.

- Помните о различиях между BaseException и Exception.

Примеры кода и дополнительные материалы можно найти в официальной документации