Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

How can an exception be re raised?

Problem – Reraising the exception, that has been caught in the except block. Code #1: Using raise statement all by itself. This problem typically arises when there is no need to take any action in response to an exception (e.g., logging, cleanup, etc.).

Can you raise exception in except block?

Catching Python Exceptions with Try-Except-Else-FinallyThe “finally” block runs whether or not the “try” block's code raises an exception. If there's an exception, the code in the corresponding “except” block will run, and then the code in the “finally” block will run.

How do you're raise the exception currently being handled Python?

Python Language Exceptions Re-raising exceptions In this case, simply use the raise statement with no parameters. But this has the drawback of reducing the exception trace to exactly this raise while the raise without argument retains the original exception trace.

How do you raise an exception in an except block in Python?

In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause. We can thus choose what operations to perform once we have caught the exception.


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 six


try:
    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

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