Пользовательские исключения в Python: практическое руководство
Пользовательские исключения в Python
В этом уроке вы научитесь определять собственные исключения, адаптированные под ваши нужды, с практическими примерами.
Python предоставляет множество встроенных исключений, сигнализирующих об ошибках, когда программа сталкивается с неожиданными условиями. Однако бывают случаи, когда встроенные не описывают точно проблему, с которой вы столкнулись. В таких случаях можно создавать свои собственные типы исключений, чтобы сделать код понятнее и проще в поддержке.
Создание пользовательских исключений
Определение пользовательского исключения в Python простое: создайте новый класс, наследующийся от встроенного класса Exception (или одного из его подклассов). Большинство стандартных исключений наследуются от Exception, поэтому ваш пользовательский класс бесшовно интегрируется в систему обработки ошибок Python.
> >>> class CustomError(Exception):
... pass
...
> >>> raise CustomError
Traceback (most recent call last):
...
__main__.CustomError
> >>> raise CustomError("An error occurred")
Traceback (most recent call last):
...
__main__.CustomError: An error occurred
Здесь CustomError — пользовательское исключение, наследующееся от Exception. Его можно возбуждать с raise и опциональным сообщением. В крупных проектах принято помещать все пользовательские исключения в отдельный модуль (например, exceptions.py или errors.py), чтобы их было легко находить и поддерживать.
Пример: Пользовательское исключение в Python
Следующая программа демонстрирует, как пользовательские исключения могут направлять ввод пользователя. Она многократно запрашивает число, пока пользователь не угадает заданное значение. Программа даёт подсказку — слишком велико или слишком мало — возбуждая соответствующее исключение.
# определение пользовательских исключений Python
class Error(Exception):
"""Базовый класс для других исключений"""
pass
class ValueTooSmallError(Error):
"""Возникает, когда входное значение слишком мало"""
pass
class ValueTooLargeError(Error):
"""Возникает, когда входное значение слишком велико"""
pass
# целевое число
number = 10
# продолжать запрашивать, пока не угадают
while True:
try:
i_num = int(input("Enter a number: "))
if i_num < number:
raise ValueTooSmallError
elif i_num > number:
raise ValueTooLargeError
break
except ValueTooSmallError:
print("This value is too small, try again!")
print()
except ValueTooLargeError:
print("This value is too large, try again!")
print()
print("Congratulations! You guessed it correctly.")
Пример запуска:
Enter a number: 12 This value is too large, try again! Enter a number: 0 This value is too small, try again! Enter a number: 8 This value is too small, try again! Enter a number: 10 Congratulations! You guessed it correctly.
В этом примере базовый класс Error предоставляет общего предка для двух конкретных типов ошибок. Такой подход сохраняет иерархию исключений чистой и позволяет перехватывать все связанные ошибки одной клаузой except Error, если нужно.
Настройка классов исключений
Пользовательские исключения могут также хранить дополнительные данные или выдавать более информативные сообщения. Для этого нужно переопределить __init__ и опционально __str__. Ниже иллюстрируется сценарий валидации зарплаты.
class SalaryNotInRangeError(Exception):
"""Исключение, возбуждаемое при ошибках во входной зарплате.
Attributes:
salary -- входная зарплата, вызвавшая ошибку
message -- объяснение ошибки
"""
def __init__(self, salary, message="Salary is not in (5000, 15000) range"):
self.salary = salary
self.message = message
super().__init__(self.message)
salary = int(input("Enter salary amount: "))
if not 5000 < salary < 15000:
raise SalaryNotInRangeError(salary)
Вывод
Enter salary amount: 2000 Traceback (most recent call last): File "<string>", line 17, in <module> raise SalaryNotInRangeError(salary) __main__.SalaryNotInRangeError: Salary is not in (5000, 15000) range
Переопределяя __init__, исключение может нести виновное значение. Если нужно пользовательское строковое представление, переопределите __str__, как показано ниже:
class SalaryNotInRangeError(Exception):
"""Исключение, возбуждаемое при ошибках во входной зарплате.
Attributes:
salary -- входная зарплата, вызвавшая ошибку
message -- объяснение ошибки
"""
def __init__(self, salary, message="Salary is not in (5000, 15000) range"):
self.salary = salary
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.salary} → {self.message}'
salary = int(input("Enter salary amount: "))
if not 5000 < salary < 15000:
raise SalaryNotInRangeError(salary)
Вывод
Enter salary amount: 2000 Traceback (most recent call last): File "/home/user/untitled.py", line 20, in <module> raise SalaryNotInRangeError(salary) __main__.SalaryNotInRangeError: 2000 → Salary is not in (5000, 15000) range
Для глубокого погружения в паттерны обработки исключений см. Python Exception Handling.
Чтобы узнать больше о проектировании надёжных приложений, изучите Python Object‑Oriented Programming.
Python
- Освоение типов данных в Python: практическое руководство
- Мастерство операторов Python: Полное руководство
- Оператор pass в Python: практическое руководство
- Аргументы функций в Python: позиционные, именованные и параметры по умолчанию
- Словари в Python: создание, манипуляции и продвинутые техники
- Ошибки и встроенные исключения в Python: полное руководство
- Объектно-ориентированное программирование в Python: классы, наследование, инкапсуляция и полиморфизм
- Наследование в Python: концепции, синтаксис и практические примеры
- Итераторы в Python: как они работают и как создать свои
- Понимание type() и isinstance() в Python: практические примеры