raise <expression> # Основной способ вызвать ошибку: raise Exception('Какой-то текст')
Инструкция raise
позволяет программисту:
try/except
, чтобы его можно было обработать дальше по стеку вызовов. Инструкция raise
позволяет программисту принудительно вызвать указанное исключение. Например:
>>> raise NameError('HiThere') # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # NameError: HiThere
В общем случае инструкция raise
повторно вызывает последнее исключение, которое было активным в текущей области видимости. Если нужно определить, было ли вызвано исключение, но не обрабатывать его, более простая форма инструкции raise
позволяет повторно вызвать исключение:
try: raise NameError('HiThere') except NameError: print('Исключение пролетело незаметно!') # Еще какие-то действия, например запись в журнал логов ... # затем повторно вызываем `NameError` raise # Исключение пролетело незаметно! # Traceback (most recent call last): # File "<stdin>", line 2, in <module> # NameError: HiThere
Если в текущей области видимости нет активного исключения, то в месте, где указана инструкция raise
, без указания <expression>
, возникает исключение RuntimeError
, указывающее на ошибку.
>>> raise # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # RuntimeError: No active exception to reraise
В противном случае raise
вычисляет первое выражение <expression>
как объект исключения. Он должен быть подклассом BaseException
, например Exception
или один из его подклассов. Если передается класс исключения, он будет неявно создан путем вызова его конструктора без аргументов.
# сокращение для 'raise ValueError()' >>> raise ValueError # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # ValueError
При возникновении исключения объект traceback
обычно создается автоматически и присоединяется к нему в качестве атрибута __traceback__
. Следовательно можно создать исключение путем raise
и установить в него свой собственный traceback
за один шаг, используя метод BaseException.with_traceback()
, например:
try: ... except SomeException: # Получаем трассировку tb = sys.exception().__traceback__ # передаем трассировку raise AnyException(...).with_traceback(tb)
raise
и цепочка исключений.Если внутри раздела except
(конструкции try/except
) появляется НЕперехваченное исключение (например с помощью raise
), то к нему будет привязано исключение, которое было перехвачено инструкцией except
в качестве атрибута __cause__
, и оба будут выведены в сообщении об ошибке:
try: open("database.sqlite") except OSError: raise RuntimeError("не удается обработать ошибку") # Traceback (most recent call last): # File "<stdin>", line 2, in <module> # FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite' # During handling of the above exception, another exception occurred: # Traceback (most recent call last): # File "<stdin>", line 4, in <module> # RuntimeError: не удается обработать ошибку
Подобный механизм работает неявно, если исключение вызывается внутри обработчика исключений (внутри предложения try
) или внутри предложения finally
, то предыдущее исключение присоединяется в качестве атрибута __context__
нового исключения:
Оператор raise
допускает необязательное предложение from
, которое используется для указания того, что одно исключение является прямым следствием другого:
def func(): raise ConnectionError try: func() except ConnectionError as exc: raise RuntimeError('Не удалось открыть базу данных') from exc # Traceback (most recent call last): # File "<stdin>", line 2, in <module> # File "<stdin>", line 2, in func # ConnectionError # The above exception was the direct cause of the following exception: # Traceback (most recent call last): # File "<stdin>", line 4, in <module> # RuntimeError: Не удалось открыть базу данных
Цепочка исключений может быть явно подавлена/отключена путем указания значения None
в предложении from
:
try: a = 1 / 0 except Exception as exc: raise RuntimeError("Случилось что-то плохое") from None # Traceback (most recent call last): # File "<stdin>", line 4, in <module> # RuntimeError: Случилось что-то плохое
# например, поступили данные с клавиатуры s = 'apple' try: # пытаемся преобразовать данные num = int(s) except ValueError: raise ValueError("Строка не может быть преобразована в целое число") from None # Traceback (most recent call last): # File "<stdin>", line 5, in <module> # ValueError: Строка не может быть преобразована в целое число