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

Python3.11/3.12自定义日志级别调用方信息异常问题

解决Python 3.11+自定义日志级别调用方信息错误问题

问题根源在于Python 3.11对日志模块的栈帧遍历逻辑做了调整,你用lambda包装logger._log()的方式会额外增加一层栈帧,导致日志模块错误地将lambda所在的日志模块文件识别为调用位置,而非实际业务代码的调用点。

修复方案:显式指定stacklevel参数,跳过自定义方法的栈帧

Python 3.8+的日志模块支持stacklevel参数,用于告诉日志模块需要跳过多少层栈帧来定位实际调用位置。以下是两种可靠的实现方式:

方式1:自定义Logger类(推荐,更规范)

import logging

class CustomLogger(logging.Logger):
    def custom(self, msg, *args, **kwargs):
        # stacklevel=2 跳过当前custom方法的栈帧,指向实际调用处
        kwargs.setdefault('stacklevel', 2)
        # 使用公开的log方法替代私有_log,提升兼容性
        self.log(25, msg, *args, **kwargs)

# 注册自定义Logger类
logging.setLoggerClass(CustomLogger)
logger = logging.getLogger(__name__)
# 添加自定义级别名称
logging.addLevelName(25, 'CUSTOM')

# 测试调用
def test_business_code():
    logger.custom("自定义级别日志内容")

test_business_code()

方式2:直接给Logger实例绑定自定义函数

如果不想自定义Logger类,也可以直接给现有Logger实例添加方法:

import logging

logger = logging.getLogger(__name__)
logging.addLevelName(25, 'CUSTOM')

def custom_log(msg, *args, **kwargs):
    kwargs.setdefault('stacklevel', 2)
    logger.log(25, msg, *args, **kwargs)

# 绑定到logger实例
logger.custom = custom_log

为什么原来的lambda方式失效?

Python 3.11+优化了日志模块获取调用方信息的逻辑,默认栈帧遍历的起始点更贴近底层。lambda作为匿名函数会额外生成一层栈帧,而旧代码没有指定stacklevel,导致日志模块停留在lambda所在的栈帧,最终显示日志模块内部的文件和lambda函数信息。

通过显式设置stacklevel=2,日志模块会跳过自定义方法/函数的栈帧,直接定位到业务代码中调用logger.custom()的位置,恢复正确的pathname、函数名和行号信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:07:04