Exception traceback is hidden if not re-raised immediately
A blank raise
raises the last exception.
# need to re-raise err so caller can do its own handlingif err: raise
If you use raise something
Python has no way of knowing if something
was an exception just caught before, or a new exception with a new stack trace. That's why there is the blank raise
that preserves the stack trace.
It is possible to modify and rethrow an exception:
If no expressions are present,
raise
re-raises the last exception that was active in the current scope. If no exception is active in the current scope, aTypeError
exception is raised indicating that this is an error (if running under IDLE, aQueue.Empty
exception is raised instead).Otherwise,
raise
evaluates the expressions to get three objects, usingNone
as the value of omitted expressions. The first two objects are used to determine the type and value of the exception.If a third object is present and not
None
, it must be a traceback object (see section The standard type hierarchy), and it is substituted instead of the current location as the place where the exception occurred. If the third object is present and not a traceback object orNone
, aTypeError
exception is raised.The three-expression form of
raise
is useful to re-raise an exception transparently in anexcept
clause, butraise
with no expressions should be preferred if the exception to be re-raised was the most recently active exception in the current scope.
So if you want to modify the exception and rethrow it, you can do this:
try: buggy_code_which_throws_exception()except Exception as e: raise Exception, "The code is buggy: %s" % e, sys.exc_info()[2]
You can get a lot of information about the exception via the sys.exc_info()
along with the traceback module
try the following extension to your code.
import sysimport tracebackdef func1(): func2()def func2(): raise Exception('test error')def main(): try: func1() except: exc_type, exc_value, exc_traceback = sys.exc_info() # Do your verification using exc_value and exc_traceback print "*** print_exception:" traceback.print_exception(exc_type, exc_value, exc_traceback, limit=3, file=sys.stdout)if __name__ == '__main__': main()
This would print, similar to what you wanted.
*** print_exception:Traceback (most recent call last): File "err_test.py", line 14, in main func1() File "err_test.py", line 5, in func1 func2() File "err_test.py", line 8, in func2 raise Exception('test error')Exception: test error