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