17

I'm building a tool where as exceptions propagate upwards, new data about the context of the exception gets added to the exception. The issue is, by the time the exception gets to the top level, all of the extra context data is there, but only the very latest stack trace is shown. Is there an easy way to have an exception show the original stack trace in which it was thrown instead of the last stack trace, or should I do something like grab the original stack trace the first time that the exception propagates?

For example, the following code:

def a():
 return UNBOUND
def b():
 try:
 a()
 except Exception as e:
 raise e
b()

yields the following exception:

Traceback (most recent call last):
 File "test.py", line 8, in <module>
 b()
 File "test.py", line 7, in b
 raise e
NameError: global name 'UNBOUND' is not defined

where, ideally, I'd like to somehow show the user this:

Traceback (most recent call last):
 File "test.py", line 8, in <module>
 File "test.py", line 2, in a
 return UNBOUND
NameError: global name 'UNBOUND' is not defined

As that points the user to the line that the error originally occurred on.

Lesmana
27.3k12 gold badges84 silver badges87 bronze badges
asked Dec 11, 2009 at 23:37
1
  • In Python 3.x, I also see a() in the stack trace. Traceback (most recent call last): File "py3.py", line 13, in <module> b() File "py3.py", line 12, in b raise e File "py3.py", line 10, in b a() File "py3.py", line 7, in a return UNBOUND NameError: name 'UNBOUND' is not defined Commented Dec 13, 2019 at 21:08

1 Answer 1

38

Python exceptions are a bit like java, there is a way to cause the exception to be rethrown without truncating the stack.

Just use raise without an argument. The result it:

Traceback (most recent call last):
 File "./exc.py", line 11, in <module>
 b()
 File "./exc.py", line 7, in b
 a()
 File "./exc.py", line 4, in a
 return UNBOUND
NameError: global name 'UNBOUND' is not defined

You can modify some things about the e object, even if you just raise without that argument - for example:

e.args = ("hi!",)
raise 

will actually change the exception message. You can probably change the other options too this way - without destroying the stack.

answered Dec 11, 2009 at 23:49
Sign up to request clarification or add additional context in comments.

2 Comments

I've been writing Python code for ages and I didn't know about this... Great answer. But I can't find anything written about it in the Python docs?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.