Разница заключается в том, что при использовании 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__
атрибута (который доступен для записи). Если возникшее исключение не обработано, будут напечатаны оба исключения:
>>> 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
Также см. Документацию « Встроенные исключения» для получения подробной информации о контексте и информации о причинах, прикрепленной к исключениям.