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

Python自定义Logging子类无法正确获取实例的问题排查

问题原因与解决方案

问题根源

  1. 你直接手动实例化CustomLogger的方式,不会将该实例注册到logging模块内部维护的logger注册表中。logging模块的logging.getLogger(name)方法只会从自身的内部字典中查找对应名称的logger实例,你手动创建的实例不在这个字典里。
  2. 后续调用logging.setLoggerClass(CustomLogger)后,getLogger会创建一个全新的CustomLogger实例并注册到注册表,和你之前手动创建的完全是两个独立对象,自然没有之前添加的handler和extra属性。

正确实现方式

要让getLogger能获取到同一个配置好的实例,必须遵循logging模块的规范:先设置自定义Logger类,再通过getLogger创建/获取实例,同时修复代码中的可变默认参数坑。

修正后的代码

import logging
from logging import Formatter

class CustomLogger(logging.Logger):
    def __init__(self, name, extra=None):
        super().__init__(name)
        # 修复可变默认参数的坑:避免多个实例共享同一个字典
        self.extra = extra if extra is not None else {}

    def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False, **kwargs):
        # 安全合并extra:传入的extra优先,再合并实例自带的extra
        combined_extra = {}
        if extra is not None:
            combined_extra.update(extra)
        combined_extra.update(self.extra)
        super()._log(level, msg, args, exc_info, combined_extra, stack_info, **kwargs)

# 先设置自定义Logger类,再通过getLogger获取实例
logging.setLoggerClass(CustomLogger)
logger = logging.getLogger("test-logger")
# 给实例绑定extra属性
logger.extra = {"instance_name": "name", "instance_id": 12}

# 配置handler和formatter
console_handler = logging.StreamHandler()
formatter = Formatter(
    "%(asctime)s - %(levelname)s - instance name: %(instance_name)s - instance id: %(instance_id)i - %(message)s"
)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)

验证效果

logger.info("Hello world")
# 输出:2024-xx-xx xx:xx:xx,xxx - INFO - instance name: name - instance id: 12 - Hello world

# 再次获取同一个实例
retrieved_logger = logging.getLogger("test-logger")
print(logger is retrieved_logger)  # 输出:True
retrieved_logger.info("Hello again")  # 正常输出日志
print(retrieved_logger.handlers)  # 输出包含之前添加的StreamHandler

关键细节补充

  • 可变默认参数extra={}的问题:Python中函数默认参数在定义时就会创建,多个实例会共享同一个字典,导致意外的属性污染,用extra=None然后在内部初始化是正确做法。
  • 合并extra时,先复制传入的extra(如果存在)再合并实例的extra,避免修改外部传入的可变字典对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:36:19