32

Вручную вызов (бросание) исключения в Python

22

Как поднять исключение в Python, чтобы его можно было перехватить позже с помощью блока except?

5 ответ(ов)

1

В Python 3 существует четыре различных синтаксиса для генерации исключений:

  1. raise exception
  2. raise exception (args)
  3. raise
  4. 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 --  деление на ноль
Мое исключение Деление на ноль
деление на ноль
0

В общем случае, когда необходимо выбросить исключение в ответ на некоторые неожиданные условия, и вы никогда не собираетесь его перехватывать, а просто хотите быстро выявить ошибку для последующей отладки — наиболее логичным вариантом кажется использование AssertionError:

if 0 < distance <= RADIUS:
    # Выполнить что-то.
elif RADIUS < distance:
    # Выполнить что-то другое.
else:
    raise AssertionError("Неожиданное значение 'distance'!", distance)

Использование AssertionError в данном контексте позволяет достаточно быстро определить место возникновения проблемы, так как это исключение сигнализирует о наличии логической ошибки в коде.

0

Обратите внимание, что вы можете вызывать исключения с аргументами или без них.

Пример:

raise SystemExit

Этот код завершает программу, но вам может быть интересно знать, что произошло. В таком случае вы можете использовать следующий код:

raise SystemExit("программа завершилась")

Этот код выведет "программа завершилась" в стандартный поток ошибок перед закрытием программы.

0

Просто хочу отметить, что бывают случаи, когда нужно обрабатывать общие исключения. Если вы обрабатываете множество файлов и записываете ошибки в журнал, может возникнуть необходимость поймать любую ошибку, возникающую при обработке конкретного файла, зафиксировать её и продолжить обработку остальных файлов. В таком случае блок кода выглядит следующим образом:

try:
    foo()
except Exception as e:
    print(e)  # Выводим обработанную ошибку

Однако следует помнить, что вам всё равно необходимо использовать raise для специфических исключений, чтобы понимать, что они означают.

0

Вы также можете создавать пользовательские исключения. Например, если вы пишете библиотеку, то хорошей практикой будет создать базовый класс исключения для вашего модуля, а затем определить конкретные подклассы исключений для более точного описания ошибок.

Это можно сделать следующим образом:

class MyModuleBaseClass(Exception):
    pass

class MoreSpecificException(MyModuleBaseClass):
    pass

# Чтобы вызвать пользовательские исключения, просто используйте
# ключевое слово raise
raise MoreSpecificException
raise MoreSpecificException('сообщение')

Если вас не интересует создание пользовательского базового класса, вы можете просто наследовать ваши пользовательские классы исключений от обычных классов исключений, таких как Exception, TypeError, ValueError и т.д.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь