Reputation: 974
In Python 3, there's a useful raise ... from ...
feature to re-raise an exception. That said, how do you find the original (/ re-raised) exception from the raised exception? Here's a (silly) example with comments to demonstrate what I mean--
def some_func():
try:
None() # TypeError: 'NoneType' object is not callable
except as err:
raise Exception("blah") from err
try:
some_func()
except as err:
# how can I access the original exception (TypeError)?
Upvotes: 2
Views: 940
Reputation: 19352
Whenever an exception is raised from an exception handler (the except
clause), the original exception will bestored in new exception's __context__
.
Whenever an exception is raised using from
syntax, the exception specified in from
will be saved in the __cause__
attribute of the new exception.
In the usual use case, that amounts to both __cause__
and __context__
containing the original exception:
def f():
try:
raise Exception('first exception')
except Exception as e:
raise Exception('second exception') from e
try:
f()
except Exception as e:
print('This exception', e)
print('Original exception', e.__context__)
print('Also original exception', e.__cause__)
Here is also an example of when __context__
is set:
try:
raise Exception('first exception')
except Exception as e:
raise Exception('second exception')
and an example of when __cause__
is set:
e = Exception('first exception')
raise Exception('second exception') from e
Upvotes: 2
Reputation: 160417
It's in the __cause__
attribute of the raised exception. Taken from the docs on the raise
statement it says regarding raise ... from ...
:
The
from
clause 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.
So, in your given scenario, repr
ing the __cause__
attribute:
def some_func():
try:
None() # TypeError: 'NoneType' object is not callable
except TypeError as err:
raise Exception("blah") from err
try:
some_func()
except Exception as er:
print(repr(er.__cause__))
Will print out:
TypeError("'NoneType' object is not callable",)
Upvotes: 4