Python raise from usage
The difference is that when you use
__cause__ attribute is set and the message states that the exception was directly caused by. If you omit the
from then no
__cause__ is set, but the
__context__ attribute may be set as well, and the traceback then shows the context as during handling something else happened.
__context__ happens if you used
raise in an exception handler; if you used
raise anywhere else no
__context__ is set either.
__cause__ is set, a
__suppress_context__ = True flag is also set on the exception; when
__suppress_context__ is set to
__context__ is ignored when printing a traceback.
When raising from a exception handler where you dont want to show the context (dont want a during handling another exception happened message), then use
raise ... from None to set
In other words, Python sets a context on exceptions so you can introspect where an exception was raised, letting you see if another exception was replaced by it. You can also add a cause to an exception, making the traceback explicit about the other exception (use different wording), and the context is ignored (but can still be introspected when debugging). Using
raise ... from None lets you suppress the context being printed.
raise statement documenation:
fromclause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the
__cause__attribute (which is writable). If the raised exception is not handled, both exceptions will be printed:
>>> 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
A similar mechanism works implicitly if an exception is raised inside an exception handler or a
finallyclause: the previous exception is then attached as the new exception’s
>>> 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
Also see the Built-in Exceptions documentation for details on the context and cause information attached to exceptions.