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

折月煮酒 提交于 2019-11-27 11:59:53

You can 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

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

try:
    something()
except SomeError as e:
    try:
        plan_B()
    except AlsoFailsError:
        raise e

The only problem with the above is that it will produce a slightly misleading traceback that tells you that SomeError occurred while handling AlsoFailsError (because of raise e inside except AlsoFailsError), where in fact the almost exact opposite occurred - we handled AlsoFailsError while trying to recover from SomeError. To disable this behavior and get a traceback that never mentions AlsoFailsError, replace raise e with raise e from None.

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 six


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

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
Matthias Urlichs

Python 3.5+ attaches the traceback information to the error anyway, so it's no longer necessary to save it separately.

>>> def f():
...   try:
...     raise SyntaxError
...   except Exception as e:
...     err = e
...     try:
...       raise AttributeError
...     except Exception as e1:
...       raise err from None
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in f
  File "<stdin>", line 3, in f
SyntaxError: None
>>> 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!