Python3中自定义全级别日志格式化失效,Python2原有代码为何无效?
Python2到Python3自定义日志格式化失效的原因及修复
我之前也踩过这个坑!你在Python2里写的SimpleFormatter到Python3里没效果,核心是Python3对logging.Formatter的内部实现做了关键变更:
关键变更点
- 在Python2中,
Formatter每次格式化日志时都会直接读取_fmt属性定义的格式字符串,所以你在format方法里动态修改self._fmt能立刻生效。 - 但Python3里,
Formatter初始化后(或第一次调用format方法后),会根据_fmt创建一个**_style缓存对象**(比如对应百分号格式的PercentStyle),后续所有格式化操作都会直接复用这个缓存对象,不会再读取_fmt的最新值。所以你修改self._fmt后,_style还是原来的旧缓存,自然看不到格式变化。
修复方法
方法一:修改_fmt后重置_style
直接在format方法里更新_fmt后,强制重置_style让它重新基于新格式生成:
class SimpleFormatter(logging.Formatter): FORMATS = { logging.DEBUG: "[D][%(module)s] {%(filename)s:%(lineno)d %(funcName)s} %(message)s", logging.INFO: "%(message)s", logging.WARNING: "[-][%(module)s] %(message)s", logging.ERROR: "[!][%(module)s] %(message)s", logging.CRITICAL: "[!][%(module)s] %(message)s", 'DEFAULT': "[%(levelname)s] %(message)s" } def format(self, record): self._fmt = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) # 重置_style,使其重新基于新的_fmt创建 self._style = self._get_style(self._fmt) return super().format(record)
方法二:重写formatMessage方法(更推荐)
这种方式更贴合Python3 logging的设计逻辑,避免修改内部缓存属性,稳定性更好:
class SimpleFormatter(logging.Formatter): FORMATS = { logging.DEBUG: "[D][%(module)s] {%(filename)s:%(lineno)d %(funcName)s} %(message)s", logging.INFO: "%(message)s", logging.WARNING: "[-][%(module)s] %(message)s", logging.ERROR: "[!][%(module)s] %(message)s", logging.CRITICAL: "[!][%(module)s] %(message)s", 'DEFAULT': "[%(levelname)s] %(message)s" } def formatMessage(self, record): # 根据日志级别获取对应的格式字符串 fmt = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) # 用临时Formatter实例处理格式化,避免影响原实例状态 return logging.Formatter(fmt).formatMessage(record)
两种方法都能解决问题,第二种更符合Python3的编码习惯,推荐优先使用。
内容的提问来源于stack exchange,提问作者daisy
相关产品推荐
相关产品推荐

