As a Python developer you can choose to throw an exception if a condition occurs. To throw (or raise) an exception, use the raise keyword.
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.
The raise keyword is used to raise an exception. You can define what kind of error to raise, and the text to print to the user.
Strictly speaking you can't raise multiple exceptions but you could raise an object that contains multiple exceptions. Question: Why would you ever want to do this? Answer: In a loop when you want to raise an error but process the loop to completion.
If you're lucky enough to only support python 3.x, this really becomes a thing of beauty :)
We can chain the exceptions using raise from.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks') from e
In this case, the exception your caller would catch has the line number of the place where we raise our exception.
Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise Exception('Smelly socks') from e
Exception: Smelly socks
Notice the bottom exception only has the stacktrace from where we raised our exception. Your caller could still get the original exception by accessing the __cause__
attribute of the exception they catch.
Or you can use with_traceback.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks').with_traceback(e.__traceback__)
Using this form, the exception your caller would catch has the traceback from where the original error occurred.
Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise Exception('Smelly socks').with_traceback(e.__traceback__)
File "test.py", line 2, in <module>
1 / 0
Exception: Smelly socks
Notice the bottom exception has the line where we performed the invalid division as well as the line where we reraise the exception.
Update: For Python 3, check Ben's answer
To attach a message to the current exception and re-raise it: (the outer try/except is just to show the effect)
For python 2.x where x>=6:
try:
try:
raise ValueError # something bad...
except ValueError as err:
err.message=err.message+" hello"
raise # re-raise current exception
except ValueError as e:
print(" got error of type "+ str(type(e))+" with message " +e.message)
This will also do the right thing if err
is derived from ValueError
. For example UnicodeDecodeError
.
Note that you can add whatever you like to err
. For example err.problematic_array=[1,2,3]
.
Edit: @Ducan points in a comment the above does not work with python 3 since .message
is not a member of ValueError
. Instead you could use this (valid python 2.6 or later or 3.x):
try:
try:
raise ValueError
except ValueError as err:
if not err.args:
err.args=('',)
err.args = err.args + ("hello",)
raise
except ValueError as e:
print(" error was "+ str(type(e))+str(e.args))
Edit2:
Depending on what the purpose is, you can also opt for adding the extra information under your own variable name. For both python2 and python3:
try:
try:
raise ValueError
except ValueError as err:
err.extra_info = "hello"
raise
except ValueError as e:
print(" error was "+ str(type(e))+str(e))
if 'extra_info' in dir(e):
print e.extra_info
It seems all the answers are adding info to e.args[0], thereby altering the existing error message. Is there a downside to extending the args tuple instead? I think the possible upside is, you can leave the original error message alone for cases where parsing that string is needed; and you could add multiple elements to the tuple if your custom error handling produced several messages or error codes, for cases where the traceback would be parsed programmatically (like via a system monitoring tool).
## Approach #1, if the exception may not be derived from Exception and well-behaved:
def to_int(x):
try:
return int(x)
except Exception as e:
e.args = (e.args if e.args else tuple()) + ('Custom message',)
raise
>>> to_int('12')
12
>>> to_int('12 monkeys')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')
or
## Approach #2, if the exception is always derived from Exception and well-behaved:
def to_int(x):
try:
return int(x)
except Exception as e:
e.args += ('Custom message',)
raise
>>> to_int('12')
12
>>> to_int('12 monkeys')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')
Can you see a downside to this approach?
try:
try:
int('a')
except ValueError as e:
raise ValueError('There is a problem: {0}'.format(e))
except ValueError as err:
print err
prints:
There is a problem: invalid literal for int() with base 10: 'a'
This code template should allow you to raise an exception with a custom message.
try:
raise ValueError
except ValueError as err:
raise type(err)("my message")
This is the function I use to modify the exception message in Python 2.7 and 3.x while preserving the original traceback. It requires six
def reraise_modify(caught_exc, append_msg, prepend=False):
"""Append message to exception while preserving attributes.
Preserves exception class, and exception traceback.
Note:
This function needs to be called inside an except because
`sys.exc_info()` requires the exception context.
Args:
caught_exc(Exception): The caught exception object
append_msg(str): The message to append to the caught exception
prepend(bool): If True prepend the message to args instead of appending
Returns:
None
Side Effects:
Re-raises the exception with the preserved data / trace but
modified message
"""
ExceptClass = type(caught_exc)
# Keep old traceback
traceback = sys.exc_info()[2]
if not caught_exc.args:
# If no args, create our own tuple
arg_list = [append_msg]
else:
# Take the last arg
# If it is a string
# append your message.
# Otherwise append it to the
# arg list(Not as pretty)
arg_list = list(caught_exc.args[:-1])
last_arg = caught_exc.args[-1]
if isinstance(last_arg, str):
if prepend:
arg_list.append(append_msg + last_arg)
else:
arg_list.append(last_arg + append_msg)
else:
arg_list += [last_arg, append_msg]
caught_exc.args = tuple(arg_list)
six.reraise(ExceptClass,
caught_exc,
traceback)
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