Re-raise Python exception and preserve stack trace

In Python 2 you need to use all three arguments to raise:

raise failingThread.exc_info[0], failingThread.exc_info[1], failingThread.exc_info[2]

passing the traceback object in as the third argument preserves the stack.

From help('raise'):

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 or None, a TypeError exception is raised. The three-expression form of raise is useful to re-raise an exception transparently in an except clause, but raise with no expressions should be preferred if the exception to be re-raised was the most recently active exception in the current scope.

In this particular case you cannot use the no expression version.

For Python 3 (as per the comments):

raise failingThread.exc_info[1].with_traceback(failingThread.exc_info[2])

or you can simply chain the exceptions using raise ... from ... but that raises a chained exception with the original context attached in the cause attribute and that may or may not be what you want.


This code snippet works in both python 2 & 3:

      1 try:
----> 2     raise KeyError('Default key error message')
      3 except KeyError as e:
      4     e.args = ('Custom message when get re-raised',) #The comma is not a typo, it's there to indicate that we're replacing the tuple that e.args pointing to with another tuple that contain the custom message.
      5     raise