記錄異常

如果你想記錄異常,你可以並且應該使用 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