如何在Python中以自定义消息引发相同的异常?
我在代码中有一个 try
块:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise ValueError(errmsg)
严格来说,我实际上是抛出了一个 新的 ValueError
,而不是由 do_something...()
抛出的那个 ValueError
,在这个情况下它被称为 err
。我想知道如何给 err
添加一个自定义的消息?我尝试了以下代码,但失败了,因为 err
是一个 ValueError
的实例,而不是可以调用的东西:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
16 个回答
这只适用于Python 3。你可以修改异常的原始参数,并添加你自己的参数。
异常会记住它创建时的参数。我想这是为了让你可以修改这个异常。
在函数 reraise
中,我们在异常的原始参数前面加上任何我们想要的新参数(比如一条消息)。最后,我们重新抛出这个异常,同时保留追踪记录。
def reraise(e, *args):
'''re-raise an exception with extra arguments
:param e: The exception to reraise
:param args: Extra args to add to the exception
'''
# e.args is a tuple of arguments that the exception with instantiated with.
#
e.args = args + e.args
# Recreate the exception and preserve the traceback info so that we can see
# where this exception originated.
#
raise e.with_traceback(e.__traceback__)
def bad():
raise ValueError('bad')
def very():
try:
bad()
except Exception as e:
reraise(e, 'very')
def very_very():
try:
very()
except Exception as e:
reraise(e, 'very')
very_very()
输出
Traceback (most recent call last):
File "main.py", line 35, in <module>
very_very()
File "main.py", line 30, in very_very
reraise(e, 'very')
File "main.py", line 15, in reraise
raise e.with_traceback(e.__traceback__)
File "main.py", line 28, in very_very
very()
File "main.py", line 24, in very
reraise(e, 'very')
File "main.py", line 15, in reraise
raise e.with_traceback(e.__traceback__)
File "main.py", line 22, in very
bad()
File "main.py", line 18, in bad
raise ValueError('bad')
ValueError: ('very', 'very', 'bad')
更新:对于Python 3,请查看 Ben的回答
更新2023:我在十多年前写了这个回答,现在有更好的答案。你应该使用Python 3,并参考上面的回答。
原始回答:
要给当前的异常添加一条信息并重新抛出它:
(外面的try/except只是为了展示效果)
对于Python 2.x,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)
如果err
是从ValueError
派生出来的,这样做也会有效果(比如UnicodeDecodeError
)。
注意,你可以在err
中添加任何你想要的信息。例如err.problematic_array=[1,2,3]
。
编辑: @Ducan在评论中指出,上面的做法在Python 3中不适用,因为.message
不是ValueError
的一个成员。相反,你可以使用这个(适用于Python 2.6及以上版本或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))
编辑2:
根据你的目的,你也可以选择在自己的变量名下添加额外的信息。对于Python 2和Python 3都适用:
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
如果你运气好,只需要支持 Python 3.x,那这就真的变得很美妙了 :)
raise from
我们可以使用 raise from 来链接异常。
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks') from e
在这种情况下,你的调用者捕获到的异常会显示我们抛出异常的那一行的行号。
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
注意,底部的异常只包含我们抛出异常时的堆栈跟踪信息。你的调用者仍然可以通过访问他们捕获的异常的 __cause__
属性来获取原始异常。
with_traceback
或者你可以使用 with_traceback。
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks').with_traceback(e.__traceback__)
使用这种形式时,你的调用者捕获到的异常会包含原始错误发生时的堆栈跟踪信息。
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
注意,底部的异常不仅显示了我们进行无效除法的那一行,还显示了我们重新抛出异常的那一行。