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.).
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.
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.
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
>>>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With