如何记录Python异常?

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

当前回答

我要找的是:

import sys
import traceback

exc_type, exc_value, exc_traceback = sys.exc_info()
traceback_in_var = traceback.format_tb(exc_traceback)

看到的:

https://docs.python.org/3/library/traceback.html

其他回答

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

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

下面是一个简单的例子,摘自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')

要关闭其他可能在这里丢失的内容,在日志中捕获它的最佳方法是使用traceback.format_exc()调用,然后将该字符串拆分为每行,以便在生成的日志文件中捕获:

import logging
import sys
import traceback

try:
  ...
except Exception as ex:
  # could be done differently, just showing you can split it apart to capture everything individually
  ex_t = type(ex).__name__
  err = str(ex)
  err_msg = f'[{ex_t}] - {err}'
  logging.error(err_msg)

  # go through the trackback lines and individually add those to the log as an error
  for l in traceback.format_exc().splitlines():
    logging.error(l)

我就是这么做的。

try:
    do_something()
except:
    # How can I log my exception here, complete with its traceback?
    import traceback
    traceback.format_exc() # this will print a complete trace to stout.

你可以记录主线程上所有未捕获的异常,方法是将一个处理程序分配给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.