Исключения (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.
Примеры кода и дополнительные материалы можно найти в официальной документации