Короткий ответ
Собственное исключение создаётся как класс, наследующийся от Exception (или более конкретного встроенного исключения), и возбуждается через raise MyError("сообщение"); это позволяет вызывающему коду отличать именно вашу ошибку от остальных и обрабатывать её целенаправленно через except MyError.
Как это работает подробнее
Класс исключения обычно не требует собственной логики — достаточно унаследоваться от Exception или подходящего встроенного класса (например, ValueError), чтобы получить стандартное поведение хранения сообщения и трассировки стека. При raise Python прерывает обычный поток выполнения и ищет подходящий except выше по стеку вызовов.
Пример кода
example.py
class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
super().__init__(f"Недостаточно средств: баланс {balance}, нужно {amount}")
self.balance = balance
self.amount = amount
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(balance, amount)
return balance - amount
try:
withdraw(100, 150)
except InsufficientFundsError as exc:
print("Операция отклонена:", exc)
print("Не хватает:", exc.amount - exc.balance)Что использовать на практике
- Практика. Собственные исключения делают код читаемым и позволяют вызывающей стороне принимать решения в зависимости от конкретной ошибки (
except InsufficientFundsError), а не парсить текст сообщения общегоValueError. Для крупных приложений часто создают базовое исключение приложения (class AppError(Exception)), от которого наследуют все специфичные ошибки — это даёт возможность перехватывать "любую ошибку приложения" одним except.
Подводные камни
- Риски. Используют общий
Exceptionдля всех ошибок без разделения на типы, из-за чего вызывающий код вынужден либо ловить всё подряд, либо парсить текст сообщения. Также забывают вызватьsuper().__init__(message), из-за чего у исключения отсутствует читаемое текстовое представление.