Ответ 1
Разница в том, что при использовании from
__cause__
атрибут __cause__
и в сообщении указывается, что исключение было вызвано напрямую. Если вы опускаете from
тогда никакая __cause__
не установлена, но атрибут __context__
может быть установлен, и в результате трассировки отображается контекст, как во время обработки чего-то еще, что произошло.
Установка __context__
происходит, если вы использовали raise
в обработчике исключений; если вы использовали raise
любом другом месте, то __context__
не устанавливается.
Если установлена __cause__
, для __suppress_context__ = True
также устанавливается флаг __suppress_context__ = True
; если для __suppress_context__
задано значение True
, __context__
игнорируется при печати трассировки.
При возврате из обработчика исключений, когда вы не хотите показывать контекст (не хотите, чтобы во время обработки другого сообщения об исключительной ситуации), используйте raise... from None
чтобы установить для __suppress_context__
значение True
.
Другими словами, Python устанавливает контекст для исключений, чтобы вы могли проанализировать, где возникло исключение, позволяя увидеть, было ли заменено другое исключение. Вы также можете добавить причину в исключение, сделав трассировку явной для другого исключения (используйте другую формулировку), и контекст игнорируется (но все же может быть подвергнут внутреннему анализу при отладке). Использование raise... from None
позволяет вам подавить контекст печати.
См raise
выражение documenation:
Предложение
from
используется для цепочки исключений: если дано, второе выражение должно быть другим классом или экземпляром исключения, который затем будет присоединен к__cause__
исключению как атрибут__cause__
(который доступен для записи). Если возникшее исключение не обработано, будут напечатаны оба исключения:>>> try: ... print(1 / 0) ... except Exception as exc: ... raise RuntimeError("Something bad happened") from exc ... Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: int division or modulo by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<stdin>", line 4, in <module> RuntimeError: Something bad happened
Подобный механизм работает неявно, если исключение вызывается внутри обработчика исключений или предложения
finally
: предыдущее исключение затем присоединяется как атрибут__context__
новых исключений:>>> try: ... print(1 / 0) ... except: ... raise RuntimeError("Something bad happened") ... Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: int division or modulo by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 4, in <module> RuntimeError: Something bad happened
Также см. Документацию " Встроенные исключения" для получения подробной информации о контексте и сведениях о причинах, прикрепленных к исключениям.