В чем разница между raise
и raise from
в Python?
try:
raise ValueError
except Exception as e:
raise IndexError
что дает
Traceback (most recent call last):
File "tmp.py", line 2, in <module>
raise ValueError
ValueError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "tmp.py", line 4, in <module>
raise IndexError
IndexError
и
try:
raise ValueError
except Exception as e:
raise IndexError from e
что дает
Traceback (most recent call last):
File "tmp.py", line 2, in <module>
raise ValueError
ValueError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "tmp.py", line 4, in <module>
raise IndexError from e
IndexError
python
python-3.x
syntax
exception-handling
darkfeline
источник
источник
raise IndexError from None
, скажем.raise IndexError from False
Встает, аTypeError
неIndexError
. Сделал мой день.Ответы:
Разница заключается в том, что при использовании
from
, то__cause__
атрибут установлен , и сообщение заявляет , что исключение было непосредственно вызвано . Если вы опускаете,from
тогда no__cause__
устанавливается, но__context__
атрибут также может быть установлен, и затем трассировка отображает контекст, как во время обработки чего-то еще произошло .Установка
__context__
происходит, если вы использовалиraise
в обработчике исключений; если вы использовалиraise
где-либо еще, то не__context__
устанавливается.Если
__cause__
установлено,__suppress_context__ = True
флаг также установлен на исключение; когда__suppress_context__
установлено значениеTrue
,__context__
при печати трассировки игнорируется.При вызове из обработчика исключений, когда вы не хотите показывать контекст (не хотите во время обработки другого сообщения об исключении, произошедшем ), используйте
raise ... from None
для установки__suppress_context__
значениеTrue
.Другими словами, Python устанавливает контекст для исключений, чтобы вы могли проанализировать, где возникло исключение, позволяя увидеть, было ли заменено другое исключение. Вы также можете добавить причину в исключение, сделав трассировку явной для другого исключения (используйте другую формулировку), и контекст будет проигнорирован (но все еще может подвергаться самоанализу при отладке). Использование
raise ... from None
позволяет подавить контекст печати.Смотрите документацию
raise
заявления :Также см. Документацию « Встроенные исключения» для получения подробной информации о контексте и информации о причинах, прикрепленной к исключениям.
источник
from
и__cause__
вместо неявных__context__
? Есть ли случаи, когда кто-то может присоединить исключение, отличное от того, которое поймалexcept
?DatabaseError
если открытие базы данных завершится неудачно. Но если сбой является результатом того,IOError
что файл не удалось открыть, илиHTTPError
URL-адреса не работает, то это контекст, который вы хотите явно включить, поэтому разработчик, использующий API, может отладить, почему это так. В этот момент вы используетеraise DatabaseError from original_exception
.IOError
иHTTPError
на их потребителей, то они должны использоватьraise NewException from databaseexception.__cause__
, в настоящее время используют различные исключения из ,DatabaseException
что они просто поймали.foo
и хотите создать новое исключениеbar
? Тогда вы можете использоватьraise bar from foo
и иметь состояние Python, котороеfoo
вызвано напрямуюbar
. Если вы не используетеfrom foo
, то Python будет по- прежнему печатать как, но утверждают , что во время обращенияfoo
,bar
был поднят , другое сообщение, предназначенное для флага возможную ошибку в обработке ошибок.