How to re-raise an exception in nested try/except blocks? How to re-raise an exception in nested try/except blocks? python python

How to re-raise an exception in nested try/except blocks?


As of Python 3 the traceback is stored in the exception, so a simple raise e will do the (mostly) right thing:

try:    something()except SomeError as e:    try:        plan_B()    except AlsoFailsError:        raise e  # or raise e from None - see below

The traceback produced will include an additional notice that SomeError occurred while handling AlsoFailsError (because of raise e being inside except AlsoFailsError). This is misleading because what actually happened is the other way around - we encountered AlsoFailsError, and handled it, while trying to recover from SomeError. To obtain a traceback that doesn't include AlsoFailsError, replace raise e with raise e from None.

In Python 2 you'd store the exception type, value, and traceback in local variables and use the three-argument form of raise:

try:    something()except SomeError:    t, v, tb = sys.exc_info()    try:        plan_B()    except AlsoFailsError:        raise t, v, tb


Even if the accepted solution is right, it's good to point to the Six library which has a Python 2+3 solution, using six.reraise.

six.reraise(exc_type, exc_value, exc_traceback=None)

Reraise an exception, possibly with a different traceback.[...]

So, you can write:

import sixtry:    something()except SomeError:    t, v, tb = sys.exc_info()    try:        plan_B()    except AlsoFailsError:        six.reraise(t, v, tb)


As per Drew McGowen's suggestion, but taking care of a general case (where a return value s is present), here's an alternative to user4815162342's answer:

try:    s = something()except SomeError as e:    def wrapped_plan_B():        try:            return False, plan_B()        except:            return True, None    failed, s = wrapped_plan_B()    if failed:        raise