记录异常
如果你想记录异常,你可以并且应该使用 logging.exception(msg)
方法:
>>> import logging
>>> logging.basicConfig()
>>> try:
... raise Exception('foo')
... except:
... logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: foo
不要将异常作为参数传递:
由于 logging.exception(msg)
期望一个 msg
arg,将异常传递给日志记录调用是一个常见的陷阱,如下所示:
>>> try:
... raise Exception('foo')
... except Exception as e:
... logging.exception(e)
...
ERROR:root:foo
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: foo
虽然起初看起来好像这是正确的事情,但由于异常和各种编码如何在日志记录模块中协同工作,实际上存在问题:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception(e)
...
Traceback (most recent call last):
File "/.../python2.7/logging/__init__.py", line 861, in emit
msg = self.format(record)
File "/.../python2.7/logging/__init__.py", line 734, in format
return fmt.format(record)
File "/.../python2.7/logging/__init__.py", line 469, in format
s = self._fmt % record.__dict__
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
Logged from file <stdin>, line 4
试图记录包含 unicode 字符的异常,这种方式将失败 。它将隐藏原始异常的堆栈跟踪,方法是使用在 logging.exception(e)
调用格式化期间引发的新异常覆盖它。
显然,在你自己的代码中,你可能会注意到异常中的编码。但是,第三方库可能以不同的方式处理此问题。
正确用法:
如果不是异常,你只是传递一条消息让 python 做它的魔力,它会起作用:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6
正如你所看到的,在这种情况下我们实际上并没有使用 e
,对 logging.exception(...)
的调用会神奇地格式化最近的异常。
使用非 ERROR 日志级别记录异常
如果要使用另一个日志级别而不是 ERROR 来记录异常,可以使用默认记录器的 exc_info
参数:
logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)
访问例外的消息
请注意,那里的库可能会抛出异常消息,如任何 unicode 或(如果幸运的话,utf-8)字节串。如果你真的需要访问异常的文本,唯一可行的方法就是使用 repr(e)
或%r
字符串格式:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception('received this exception: %r' % e)
...
ERROR:root:received this exception: Exception(u'f\xf6\xf6',)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6