Kit*_*Kit 123 python message exception
try
我的代码中有这个块:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise ValueError(errmsg)
Run Code Online (Sandbox Code Playgroud)
严格地说,我实际上是在另一种情况下 ValueError
,而不是ValueError
抛出的do_something...()
,err
在这种情况下被称为.如何附加自定义消息err
?我尝试下面的代码,但失败,因为err
,一个ValueError
实例,不是赎回:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
Run Code Online (Sandbox Code Playgroud)
Ben*_*Ben 136
我意识到这个问题已经存在了一段时间,但是一旦你足够幸运只支持python 3.x,这真的变得美丽了:)
我们可以使用raise from来链接异常.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks') from e
Run Code Online (Sandbox Code Playgroud)
在这种情况下,调用者将捕获的异常具有我们引发异常的地方的行号.
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
Run Code Online (Sandbox Code Playgroud)
注意底部异常只有我们引发异常的堆栈跟踪.您的调用者仍然可以通过访问__cause__
他们捕获的异常的属性来获取原始异常.
或者你可以使用with_traceback.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks').with_traceback(e.__traceback__)
Run Code Online (Sandbox Code Playgroud)
使用此表单,调用者将捕获的异常具有发生原始错误的位置的回溯.
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
Run Code Online (Sandbox Code Playgroud)
请注意,底部异常具有我们执行无效除法的行以及我们重新加载异常的行.
Joh*_*erg 81
更新:对于Python 3,请查看Ben的答案
将消息附加到当前异常并重新提升它:(外部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)
Run Code Online (Sandbox Code Playgroud)
这也将做正确的事情,如果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))
Run Code Online (Sandbox Code Playgroud)
EDIT2:
根据目的,您还可以选择在自己的变量名称下添加额外信息.对于python2和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
Run Code Online (Sandbox Code Playgroud)
shr*_*use 18
这只适用于 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()
Run Code Online (Sandbox Code Playgroud)
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')
Run Code Online (Sandbox Code Playgroud)
wim*_*wim 15
PEP 678 \xe2\x80\x93 用注释丰富异常已被接受并登陆 Python 3.11。新的 API 允许用户将自定义消息附加到现有错误。这对于在遇到错误时添加附加上下文很有用。
\n使用该add_note
方法适合回答原问题:
try:\n int("eleven")\nexcept ValueError as e:\n errmsg = "My custom error message."\n e.add_note(errmsg)\n raise\n
Run Code Online (Sandbox Code Playgroud)\n它会渲染成这样:
\nTraceback (most recent call last):\n File "/tmp/example.py", line 2, in <module>\n int("eleven")\nValueError: invalid literal for int() with base 10: \'eleven\'\nMy custom error message.\n
Run Code Online (Sandbox Code Playgroud)\n修改args
用于BaseException.__str__
呈现异常的属性是唯一的方法。您可以扩展参数:
try:\n int("eleven")\nexcept ValueError as e:\n errmsg = "My custom error message."\n e.args += (errmsg,)\n raise e\n
Run Code Online (Sandbox Code Playgroud)\n它将呈现为:
\nTraceback (most recent call last):\n File "/tmp/example.py", line 2, in <module>\n int("eleven")\nValueError: ("invalid literal for int() with base 10: \'eleven\'", \'My custom error message.\')\n
Run Code Online (Sandbox Code Playgroud)\n或者您可以替换args[0]
,这有点复杂,但会产生更清晰的结果。
try:\n int("eleven")\nexcept ValueError as e:\n errmsg = "My custom error message."\n args = e.args\n if not args:\n arg0 = errmsg\n else:\n arg0 = f"{args[0]}\\n{errmsg}"\n e.args = (arg0,) + args[1:]\n raise\n
Run Code Online (Sandbox Code Playgroud)\n这将以与 Python 3.11+ 异常相同的方式呈现__notes__
:
Traceback (most recent call last):\n File "/tmp/example.py", line 2, in <module>\n int("eleven")\nValueError: invalid literal for int() with base 10: \'eleven\'\nMy custom error message.\n
Run Code Online (Sandbox Code Playgroud)\n
try:
try:
int('a')
except ValueError as e:
raise ValueError('There is a problem: {0}'.format(e))
except ValueError as err:
print err
Run Code Online (Sandbox Code Playgroud)
打印:
There is a problem: invalid literal for int() with base 10: 'a'
Run Code Online (Sandbox Code Playgroud)
似乎所有答案都是向e.args [0]添加信息,从而改变了现有的错误信息.相反,扩展args元组是否有缺点?我认为可能的好处是,您可以单独保留原始错误消息,以用于需要解析该字符串的情况; 你可以多元素添加到元组,如果您的自定义错误处理产生了一些消息或错误代码,对于回溯将编程解析(如通过系统监视工具)的情况下.
## 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')
Run Code Online (Sandbox Code Playgroud)
要么
## 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')
Run Code Online (Sandbox Code Playgroud)
你能看到这种方法的缺点吗?
此代码模板应允许您使用自定义消息引发异常。
try:
raise ValueError
except ValueError as err:
raise type(err)("my message")
Run Code Online (Sandbox Code Playgroud)