在Python中获取异常值

349

如果我有以下代码:

try:
    some_method()
except Exception, e:

我该如何获取这个异常值(指字符串表示)?

7个回答

484

使用str

try:
    some_method()
except Exception as e:
    s = str(e)
此外,大多数异常类都会有一个args属性。通常,args[0]将是错误信息。
需要注意的是,如果没有错误消息,仅使用str将返回空字符串,而根据pyfunc的建议使用repr将至少显示异常的类。我认为,如果您要将其打印出来,则是为了终端用户,他们不关心是什么类,只想要错误消息。
这实际上取决于您正在处理的异常类以及它是如何实例化的。您有特定的想法吗?

我正在打印这个来制作报告,str(e)应该没问题。非常感谢。 - Frias
13
我更倾向于使用 e.message,因为 args[0] 可能并不是一条消息。 - cedbeu
6
如果你想获取完整的异常信息,可以使用repr(e),例如:NameError("global name 'variable' is not defined",)。这样可以得到完整的异常信息,而不是仅仅“global name 'variable' is not defined”这句话。 - Ben Morris
66
这个答案很危险,因为它对于像这样的Unicode异常会失败:raise Exception(u'jörn')。这种失败特别糟糕,因为你永远不会看到实际的异常,而只会看到UnicodeDecodeError。如果你不知道异常的编码(大多数情况下你都不知道),你应该处理repr(e)或者如果真的需要的话,在异常处理中使用另一个try-except块来捕获UnicodeDecodeErrors,并退回repr(e) - Jörn Hees
14
同意@JörnHees的观点。由于Unicode处理问题,我已经数不清有多少次因str(或甚至是unicode.format)而导致错误。如果您无法完全控制错误消息内容,请始终使用repr以避免意外的Unicode错误。 - Kenny Trytek
显示剩余2条评论

288

使用 repr() 和使用 str() 的区别

使用 repr

>>> try:
...     print(x)
... except Exception as e:
...     print(repr(e))
... 
NameError("name 'x' is not defined")

使用str函数:

>>> try:
...     print(x)
... except Exception as e:
...     print(str(e))
... 
name 'x' is not defined

8
啊,repr 很有用,多谢了。似乎其他任何关于 unicodestr、编码等方面的代码都可能会因输入而引发异常。当试图保持异常外观时,这种情况并不是很有用,但是 repr 似乎是“异常安全”的。 - dashesy
8
这比任何类似于 str() 的解决方案都要好得多,因为它实际上包括了异常的类型。使用 str() 我得到了 'status',而使用 repr() 我得到了 KeyError('status'),然后我就明白了错误的原因。 - jlh

49

虽然我知道这是一个旧问题,但我想建议使用traceback模块来处理异常输出。

使用traceback.print_exc()将当前异常打印到标准错误输出流中,就像如果它未被捕获一样,或者使用traceback.format_exc()将同样的输出作为字符串返回。如果你想要限制输出,或将输出重定向到类文件对象,你可以向这两个函数传递不同的参数。


1
通常情况下,当我想要展示后台发生了什么时,我会使用str()或repr()与sys.stdout.write()一起作为警告或信息输入的选择。但是,当需要展示完整的错误跟踪而不允许程序结束时,回溯可能是一个好的选择。 - Harlin

34

还没有提供另一种方法:

try:
    1/0
except Exception, e:
    print e.message

输出:

integer division or modulo by zero

args[0] 实际上可能不是一条消息。

str(e) 返回的字符串可能带有引号并且如果是 Unicode,则可能带有前导的 u

'integer division or modulo by zero'

repr(e) 提供了完整的异常表示,这可能不是您想要的:

"ZeroDivisionError('integer division or modulo by zero',)"

编辑

糟糕!!! 似乎从 2.6 开始 BaseException.message 已被弃用,最终,明确地看来仍然没有一种标准化的方式来显示异常消息。所以我想最好的方法是根据你的需求(和可能的情况下使用 e.message 的库)来处理 e.argsstr(e)

例如,对于 pygraphvize.message 是正确显示异常的唯一方法,使用 str(e) 将用 u'' 包围消息。

但是对于 MySQLdb,检索消息的正确方式是 e.args[1]e.message 为空,而 str(e) 将显示 '(ERR_CODE, "ERR_MSG")'


6
为了检查错误消息并对其进行处理(使用Python 3)...
try:
    some_method()
except Exception as e:
    if {value} in e.args:
        {do something}

5
以下方法适用于我:
import traceback

try:
    some_method()
except Exception as e:
   # Python 3.9 or older
   print("".join(traceback.format_exception_only(type(e), e)).strip())
   # Python 3.10+
   print("".join(traceback.format_exception_only(e)).strip())

如果some_method()引发异常ValueError("asdf"),这将打印出在tracebacks中看到的内容——减去了traceback:ValueError: asdf这里有相关文档。

一个很好的例子,说明得票最高的答案不一定是最好的。 - Yair Daon
感谢您的点赞。公平地说,我的回答是在原帖发布12年后添加的。 :D - Tim Ludwinski

3

对于Python2,最好使用e.message来获取异常信息,这将避免可能的UnicodeDecodeError。但是,某些类型的异常(如OSError)中e.message将为空,在这种情况下,我们可以向日志函数添加exc_info=True以不错过错误。
对于Python3,我认为使用str(e)是安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接