背景
在一次仿真测试过程中,测试人员反馈系统启动异常,我通过查看日志文件,认为进程卡在了某个位置,但通过查看控制台日志,发现该程序抛出了未捕获的异常,但该异常信息没有在日志文件里。
于是开始寻找将非捕获的异常输出到 logging
的办法。
解决方案
参考了 《捕获全局异常,并且把异常信息打印到日志中》 这篇文章,经过验证后发现可行。
他的原理是修改全局的 exception钩子
,将其指向自定义的异常处理函数,在该函数内,统一将异常输出到 logger 中。
import logging
import sys
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s',
filename='exception.log',
filemode='a+')
# 定义一个异常捕获函数
def handle_exception(exc_type, exc_obj, exc_traceback):
"""异常捕获函数
Args:
exc_type (type): 异常类型
exc_obj (Error): 异常对象
exc_traceback (traceback): traceback对象
"""
# 将Ctrl+C异常抛出到默认except钩子,不做处理
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_obj, exc_traceback)
return
logging.exception("Unhandled Exception", exc_info=(exc_type, exc_obj, exc_traceback))
# 为sys的except钩子设置异常捕获函数
sys.excepthook = handle_exception
# 抛出一系列异常
# raise NameError('test')
# raise KeyboardInterrupt("")
在执行时,可以发现对于 KeyboardInterrupt
日志不会捕获,而其他的异常会正常捕获并输出到日志文件:
2025-02-14 14:34:57,299 ERROR Unhandled Exception
Traceback (most recent call last):
File "/home/wzq/python_test/exception_catch.py", line 29, in <module>
raise NameError('test')
NameError: test