Вручную вызов (бросание) исключения в Python
Как поднять исключение в Python, чтобы его можно было перехватить позже с помощью блока except
?
5 ответ(ов)
В Python 3 существует четыре различных синтаксиса для генерации исключений:
raise exception
raise exception (args)
raise
raise exception (args) from original_exception
1. Raise exception против 2. raise exception (args)
Если вы используете raise exception (args)
для генерации исключения, то args
будут напечатаны при выводе объекта исключения, как показано в примере ниже.
# Генерация исключения (args)
try:
raise ValueError("Я сгенерировал исключение")
except ValueError as exp:
print("Ошибка", exp) # Вывод -> Ошибка Я сгенерировал исключение
# Генерация исключения
try:
raise ValueError
except ValueError as exp:
print("Ошибка", exp) # Вывод -> Ошибка
3. Оператор raise
Оператор raise
без аргументов повторно генерирует последнее исключение.
Это полезно, если вам нужно выполнить некоторые действия после обработки исключения, а затем хотите снова его сгенерировать. Однако, если до этого не было исключения, оператор raise
приведет к возникновению исключения TypeError
.
def somefunction():
print("некоторое очищение")
a = 10
b = 0
result = None
try:
result = a / b
print(result)
except Exception: # Вывод ->
somefunction() # Некоторое очищение
raise # Traceback (последний вызов):
# File "python", line 9, in <module>
# ZeroDivisionError: деление на ноль
4. Raise exception (args) from original_exception
Этот оператор используется для создания цепочек исключений, в которых исключение, вызванное в ответ на другое исключение, может содержать детали оригинального исключения, как показано в следующем примере.
class MyCustomException(Exception):
pass
a = 10
b = 0
result = None
try:
try:
result = a / b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ", exp)
raise MyCustomException("Деление на ноль ") from exp
except MyCustomException as exp:
print("Мое исключение", exp)
print(exp.__cause__)
Вывод:
ZeroDivisionError -- деление на ноль
Мое исключение Деление на ноль
деление на ноль
В общем случае, когда необходимо выбросить исключение в ответ на некоторые неожиданные условия, и вы никогда не собираетесь его перехватывать, а просто хотите быстро выявить ошибку для последующей отладки — наиболее логичным вариантом кажется использование AssertionError
:
if 0 < distance <= RADIUS:
# Выполнить что-то.
elif RADIUS < distance:
# Выполнить что-то другое.
else:
raise AssertionError("Неожиданное значение 'distance'!", distance)
Использование AssertionError
в данном контексте позволяет достаточно быстро определить место возникновения проблемы, так как это исключение сигнализирует о наличии логической ошибки в коде.
Обратите внимание, что вы можете вызывать исключения с аргументами или без них.
Пример:
raise SystemExit
Этот код завершает программу, но вам может быть интересно знать, что произошло. В таком случае вы можете использовать следующий код:
raise SystemExit("программа завершилась")
Этот код выведет "программа завершилась" в стандартный поток ошибок перед закрытием программы.
Просто хочу отметить, что бывают случаи, когда нужно обрабатывать общие исключения. Если вы обрабатываете множество файлов и записываете ошибки в журнал, может возникнуть необходимость поймать любую ошибку, возникающую при обработке конкретного файла, зафиксировать её и продолжить обработку остальных файлов. В таком случае блок кода выглядит следующим образом:
try:
foo()
except Exception as e:
print(e) # Выводим обработанную ошибку
Однако следует помнить, что вам всё равно необходимо использовать raise
для специфических исключений, чтобы понимать, что они означают.
Вы также можете создавать пользовательские исключения. Например, если вы пишете библиотеку, то хорошей практикой будет создать базовый класс исключения для вашего модуля, а затем определить конкретные подклассы исключений для более точного описания ошибок.
Это можно сделать следующим образом:
class MyModuleBaseClass(Exception):
pass
class MoreSpecificException(MyModuleBaseClass):
pass
# Чтобы вызвать пользовательские исключения, просто используйте
# ключевое слово raise
raise MoreSpecificException
raise MoreSpecificException('сообщение')
Если вас не интересует создание пользовательского базового класса, вы можете просто наследовать ваши пользовательские классы исключений от обычных классов исключений, таких как Exception
, TypeError
, ValueError
и т.д.
Поймать и вывести полный трейсбек исключения в Python без остановки/выхода из программы
Как напечатать исключение в Python?
Как проверить, существует ли переменная?
Как протестировать, что функция Python вызывает исключение?
Как правильно проверить, что исключение возникает в pytest?