Reputation: 1541
I have a piece of code that I don't control and while running it raises an error. I'd like to capture the value of exc
object inside the exc_func
method.
As you can see exc_func
raises two exceptions, one of which is handled. What I care about is the value of the exc
object, but so far have little luck retrieving it. The value does not exist in exc_traceback
object and the exception message is not very helpful.
import traceback
import sys
def exc_func():
try:
a = 1
a.length()
except Exception as exc:
exc.with_not_existing()
def main():
try:
exc_func()
except Exception as exc:
exc_type, exc_value, exc_traceback = sys.exc_info()
tb_walk = traceback.walk_tb(exc_traceback)
# Need this in order to pickle traceback
tb_summary = traceback.StackSummary.extract(tb_walk, capture_locals=True)
if __name__ == '__main__':
main()
EDIT:
For instance, the exc
object in main is AttributeError("'AttributeError' object has no attribute 'with_not_existing'")
. What I really want to see is the exc
object inside exc_func
. Just to be clear, I need the exc
object itself, something like traceback.format_exc()
is not helpful in my case, due to the nature of the exception (it's a C lib that raises this exception)
Upvotes: 1
Views: 170
Reputation: 52169
When an exception is raised during handling another exception, the initial exception is stored as the __context__
. It can be extracted when handling the new exception.
try:
exc_func()
except Exception as exc:
parent = exc.__context__ # the previously handled exception
print(type(parent), parent)
Note that an exception handler may also explicitly chain exceptions via __cause__
.
Built-in Exceptions
[...]
When raising (or re-raising) an exception in an except or finally clause__context__
is automatically set to the last exception caught; if the new exception is not handled the traceback that is eventually displayed will include the originating exception(s) and the final exception.
The raise statement
[...]
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). [...]
A similar mechanism works implicitly if an exception is raised inside an exception handler or a finally clause: the previous exception is then attached as the new exception’s__context__
attribute:
Upvotes: 1