在Python中记录未捕获的异常
如何让未处理的错误通过 logging
模块输出,而不是直接输出到 stderr
呢?
我知道最好的方法是:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
但是我的情况是,如果每当出现未处理的错误时,能够自动调用 logging.exception(...)
那就太好了。
10 个回答
38
为什么不这样做:
import sys
import logging
import traceback
def log_except_hook(*exc_info):
text = "".join(traceback.format_exception(*exc_info()))
logging.error("Unhandled exception: %s", text)
sys.excepthook = log_except_hook
None()
这是使用 sys.excepthook
时的输出,如上所示:
$ python tb.py
ERROR:root:Unhandled exception: Traceback (most recent call last):
File "tb.py", line 11, in <module>
None()
TypeError: 'NoneType' object is not callable
这是将 sys.excepthook
注释掉后的输出:
$ python tb.py
Traceback (most recent call last):
File "tb.py", line 11, in <module>
None()
TypeError: 'NoneType' object is not callable
唯一的区别是,前者的第一行开头有 ERROR:root:Unhandled exception:
。
285
这里有一个完整的小例子,还包含了一些其他的小技巧:
import sys
import logging
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)
def handle_exception(exc_type, exc_value, exc_traceback):
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
if __name__ == "__main__":
raise RuntimeError("Test unhandled")
忽略 KeyboardInterrupt,这样在控制台运行的 Python 程序就可以通过 Ctrl + C 来退出。
完全依赖 Python 的日志模块来格式化异常信息。
使用一个自定义的日志记录器,并提供一个示例处理器。这个处理器会把未处理的异常输出到标准输出(stdout),而不是标准错误(stderr)。你还可以在这个日志记录器对象中添加各种不同风格的处理器。
178
正如Ned提到的,sys.excepthook
会在每次出现未处理的异常时被调用。这意味着在你的代码中,你可以改变sys.excepthook
的默认行为,做你想做的事情(比如使用logging.exception
来记录错误)。
举个简单的例子:
import sys
def foo(exctype, value, tb):
print('My Error Information')
print('Type:', exctype)
print('Value:', value)
print('Traceback:', tb)
重写sys.excepthook
:
>>> sys.excepthook = foo
故意犯一个明显的语法错误(比如漏掉冒号),然后你会看到自定义的错误信息:
>>> def bar(a, b)
My Error Information
Type: <type 'exceptions.SyntaxError'>
Value: invalid syntax (<stdin>, line 1)
Traceback: None
想了解更多关于sys.excepthook
的信息,可以查看官方文档。