如何在 Python 中正确获取异常消息

从 Python 标准库的组件中获取异常消息的最佳方法是什么?

我注意到在某些情况下,你可以像这样通过 message字段得到它:

try:
pass
except Exception as ex:
print(ex.message)

但在某些情况下(例如,在套接字错误的情况下) ,您必须执行以下操作:

try:
pass
except socket.error as ex:
print(ex)

我想知道是否有任何标准的方法来涵盖大多数这些情况?

213854 次浏览

如果查看 内置错误的文档,您将看到大多数 Exception类将它们的第一个参数分配为 message属性。但不是所有人都这样。

值得注意的是,EnvironmentError(包含子类 IOErrorOSError)的第一个参数是 errno,第二个参数是 strerror。没有 message... ... strerror大致类似于通常的 message

更一般地说,Exception的子类可以做任何它们想做的事情。它们可能有也可能没有 message属性。未来的内置 Exception可能没有 message属性。从第三方库或用户代码导入的任何 Exception子类都可能没有 message属性。

我认为处理这个问题的正确方法是确定您想要捕获的特定 Exception子类,然后只捕获这些子类,而不是使用 except Exception捕获所有的子类,然后按照您想要的方式利用特定子类定义的任何属性。

如果您必须 print的东西,我认为打印捕获的 Exception本身是最有可能做你想要的,无论它有一个 message属性或没有。

如果你愿意,你也可以检查 message 属性,像这样,但是我不会真的建议它,因为它看起来很混乱:

try:
pass
except Exception as e:
# Just print(e) is cleaner and more likely what you want,
# but if you insist on printing message specifically whenever possible...
if hasattr(e, 'message'):
print(e.message)
else:
print(e)

为了改进 @ artofwar提供的答案,下面是我认为比较简洁的检查 message属性并将其打印或将 Exception对象打印作为备用方法的方法。

try:
pass
except Exception as e:
print getattr(e, 'message', repr(e))

repr的调用是可选的,但是我发现在某些用例中它是必要的。


更新 # 1:

@ 疯狂物理学家的评论之后,这里有一个关于为什么可能需要调用 repr的证明。尝试在解释器中运行以下代码:

try:
raise Exception
except Exception as e:
print(getattr(e, 'message', repr(e)))
print(getattr(e, 'message', str(e)))

repr(e)行将打印 Exception(),而 str(e)行将打印一个空字符串。


更新 # 2:

下面是一个关于 Python 2.7和3.5的演示: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533

我也有同样的问题。我认为最好的解决方案是使用 log.eption,它会自动打印出堆栈跟踪和错误消息,比如:

try:
pass
log.info('Success')
except:
log.exception('Failed')

我也有同样的问题。深入研究之后,我发现 Exception 类有一个 args属性,它捕获用于创建异常的参数。如果您将异常缩小到一个子集,那么您应该能够确定它们是如何构造的,从而确定哪个参数包含消息。

try:
# do something that may raise an AuthException
except AuthException as ex:
if ex.args[0] == "Authentication Timeout.":
# handle timeout
else:
# generic handling
from traceback import format_exc




try:
fault = 10/0
except ZeroDivision:
print(format_exc())

另一种可能性是使用来自 traceback 模块的 format _ exc ()方法。