如何记录Python异常?

try:
    do_something()
except:
    # How can I log my exception here, complete with its traceback?

当前回答

你可以记录主线程上所有未捕获的异常,方法是将一个处理程序分配给sys. exe。excepthook,可能使用了Python日志函数的exc_info参数:

import sys
import logging

logging.basicConfig(filename='/tmp/foobar.log')

def exception_hook(exc_type, exc_value, exc_traceback):
    logging.error(
        "Uncaught exception",
        exc_info=(exc_type, exc_value, exc_traceback)
    )

sys.excepthook = exception_hook

raise Exception('Boom')

If your program uses threads, however, then note that threads created using threading.Thread will not trigger sys.excepthook when an uncaught exception occurs inside them, as noted in Issue 1230540 on Python's issue tracker. Some hacks have been suggested there to work around this limitation, like monkey-patching Thread.__init__ to overwrite self.run with an alternative run method that wraps the original in a try block and calls sys.excepthook from inside the except block. Alternatively, you could just manually wrap the entry point for each of your threads in try/except yourself.

其他回答

你可以记录主线程上所有未捕获的异常,方法是将一个处理程序分配给sys. exe。excepthook,可能使用了Python日志函数的exc_info参数:

import sys
import logging

logging.basicConfig(filename='/tmp/foobar.log')

def exception_hook(exc_type, exc_value, exc_traceback):
    logging.error(
        "Uncaught exception",
        exc_info=(exc_type, exc_value, exc_traceback)
    )

sys.excepthook = exception_hook

raise Exception('Boom')

If your program uses threads, however, then note that threads created using threading.Thread will not trigger sys.excepthook when an uncaught exception occurs inside them, as noted in Issue 1230540 on Python's issue tracker. Some hacks have been suggested there to work around this limitation, like monkey-patching Thread.__init__ to overwrite self.run with an alternative run method that wraps the original in a try block and calls sys.excepthook from inside the except block. Alternatively, you could just manually wrap the entry point for each of your threads in try/except yourself.

使用日志记录。Exception:处理程序/块中的异常,以记录当前异常和跟踪信息,并添加一条消息。

import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)

logging.debug('This message should go to the log file')

try:
    run_my_stuff()
except:
    logging.exception('Got exception on main handler')
    raise

现在查看日志文件/tmp/logging_example.out:

DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
  File "/tmp/teste.py", line 9, in <module>
    run_my_stuff()
NameError: name 'run_my_stuff' is not defined

也许没有那么时尚,但更简单:

#!/bin/bash
log="/var/log/yourlog"
/path/to/your/script.py 2>&1 | (while read; do echo "$REPLY" >> $log; done)

未捕获的异常消息将发送到STDERR,因此,您可以使用任何用于运行Python脚本的shell将STDERR发送到文件中,而不是在Python中实现日志记录。在Bash脚本中,您可以使用输出重定向来实现这一点,如Bash指南中所述。

例子

附加错误文件,其他输出到终端:

./test.py 2>> mylog.log

覆盖交错的STDOUT和STDERR输出文件:

./test.py &> mylog.log

下面是一个简单的例子,摘自python 2.6文档:

import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)

logging.debug('This message should go to the log file')