Python自定义logging子类自定义级别LogRecord属性显示异常如何修复
问题原因
logging模块默认生成LogRecord时,只会跳过logging包内的栈帧,你自定义的verbose、trace方法属于自定义类代码,不在logging包范围内,因此log方法会把这两个方法的调用位置识别为日志打印触发点,最终输出的就是自定义日志类的文件和方法名。
修复方案
方案1:使用stacklevel参数(Python 3.8+ 推荐)
Python 3.8及以上版本的Logger.log()方法支持stacklevel参数,用来指定需要向上跳过的栈层数,你的自定义方法额外多了1层调用,设置stacklevel=2即可。
import logging # 未注册自定义级别需要先添加以下4行 logging.VERBOSE = 15 logging.TRACE = 5 logging.addLevelName(logging.VERBOSE, "VERBOSE") logging.addLevelName(logging.TRACE, "TRACE") class DefaultLogger(logging.Logger): def __init__(self, name): super().__init__(name) self.propagate = True self.setLevel(logging.NOTSET) def verbose(self, msg, *args, **kwargs): # 未显式指定stacklevel时默认多跳过1层当前方法的栈帧 if 'stacklevel' not in kwargs: kwargs['stacklevel'] = 2 self.log(logging.VERBOSE, msg, *args, **kwargs) def trace(self, msg, *args, **kwargs): if 'stacklevel' not in kwargs: kwargs['stacklevel'] = 2 self.log(logging.TRACE, msg, *args, **kwargs)
方案2:兼容Python 3.8以下版本
如果需要兼容旧版本Python,可以重写findCaller方法,把自定义日志类所在的文件名加入跳过列表,查找调用栈时会自动跳过该文件的栈帧:
import logging import os # 注册自定义级别 logging.VERBOSE = 15 logging.TRACE = 5 logging.addLevelName(logging.VERBOSE, "VERBOSE") logging.addLevelName(logging.TRACE, "TRACE") class DefaultLogger(logging.Logger): # 获取当前文件绝对路径,用于标记需要跳过的栈帧 _srcfile = os.path.normcase(__file__) def __init__(self, name): super().__init__(name) self.propagate = True self.setLevel(logging.NOTSET) def findCaller(self, stack_info=False, stacklevel=1): f = logging.currentframe() # 跳过所有当前文件内的栈帧 while f: co = f.f_code filename = os.path.normcase(co.co_filename) if filename == self._srcfile: f = f.f_back continue sinfo = None if stack_info: import traceback sinfo = '\n'.join(traceback.format_stack()) return (co.co_filename, f.f_lineno, co.co_name, sinfo) return ("(unknown file)", 0, "(unknown function)", None) def verbose(self, msg, *args, **kwargs): self.log(logging.VERBOSE, msg, *args, **kwargs) def trace(self, msg, *args, **kwargs): self.log(logging.TRACE, msg, *args, **kwargs)
修改完成后调用自定义级别方法,输出的filename、funcName就会显示实际业务代码的调用位置。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

