You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python logging 修改单个handler的formatException后全handler生效问题

问题根因

这是Python logging 模块的默认设计逻辑,不是使用错误:
当日志事件携带异常信息时,第一个处理该日志的Formatter调用formatException生成异常文本后,会把结果缓存到LogRecord对象的exc_text属性中。后续处理同一条日志的其他Formatter会直接复用这个缓存的异常文本,不会再调用自己的formatException方法,因此所有异常输出都和第一个Handler(stream_handler2)的格式化结果一致。

解决方法

重写自定义Formatter类的format方法,每次处理日志前清空exc_text缓存,强制触发当前Formatter自己的formatException逻辑即可:

import logging, io, traceback


class TermFormatter(logging.Formatter):
    
    def __init__(self, *args, stack_limit=1, **kwargs):
        super().__init__(*args, **kwargs)    
        self.stack_limit = stack_limit

    def format(self, record):
        # 清空异常缓存,强制当前Formatter重新生成异常文本
        record.exc_text = None
        return super().format(record)
    
    def formatException(self, ei):
        """
        Format and return the specified exception information as a string.

        This default implementation just uses
        traceback.print_exception()
        """
        sio = io.StringIO()
        tb = ei[2]
        # See issues #9427, #1553375. Commented out for now.
        #if getattr(self, 'fullstack', False):
        #    traceback.print_stack(tb.tb_frame.f_back, file=sio)
        traceback.print_exception(ei[0], ei[1], tb, self.stack_limit, sio)
        s = sio.getvalue()
        sio.close()
        if s[-1:] == "\n":
            s = s[:-1]
        if self.stack_limit ==0:
            return "Hello my friend!"
        else:
            return s

修改后运行测试代码,输出就会符合预期:

  • F2格式的异常输出为自定义内容Hello my friend!
  • F1格式的异常输出为长度限制为2的栈追踪
  • F3格式的异常输出为默认全量栈追踪

内容的提问来源于stack exchange,提问作者hyamanieu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 05:03:00