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

同一文件中多类间Logger的传递与使用问题

Python日志类使用问题解答

原代码

import logging
import json

class logger():
  def __init__():
    self.logger = logging.getLogger(__name__)
    self.logger.setLevel(logging.INFO)
    if not (self.logger.hasHandlers()):
        #self.logger.handlers.clear()
        file_handler=logging.FileHandler("qwerty.log")
        stream_handler=logging.StreamHandler()
        format_str = {"timestamp":"%(asctime)s"} #Some more stuff
        format_str = json.dumps(format_str)
        stream_formatter=logging.Formatter(format_str)
        file_formatter=logging.Formatter(format_str)
        file_handler.setFormatter(file_formatter)
        stream_handler.setFormatter(stream_formatter)
        self.logger.addHandler(file_handler)
        self.logger.addHandler(stream_handler) 

class ABC():
    def __init__():
        logger.__init__(self)
    def some_func():
        self.logger.info("Hi from ABC")
class XYZ(ABC):
    def __init__():
        ABC.__init__(self)
        logger.__init__(self) #why do I need to do this?
    def some_func():
        self.logger.info("Hi from XYZ")

class zxc():
    def __init__():
        logger.__init__(self)
        abc = ABC()
    def some_func():
        try:
           self.logger.info("Hi from ZXC")
           raise Exception
        except:
           self.logger.error("Some issue")

问题1:子类XYZ继承已初始化logger的ABC类,为何仍需再次初始化logger?该实例不可继承吗?

不需要重复初始化,你觉得必须这么做是因为代码存在语法错误:所有__init__方法都未声明第一个参数self,导致调用ABC.__init__(self)时无法正确执行父类初始化逻辑,自然无法继承到self.logger属性。

修正语法错误后,只要ABC的__init__正确调用logger.__init__(self),XYZ继承ABC并调用ABC.__init__(self)后,会自动拥有self.logger,完全不需要单独调用logger.__init__(self)。


问题2:当前在不同类中初始化logger的方式是否正确?同一文件内多类使用logger是否有更优方案?

当前方式存在明显问题:

  1. 所有__init__方法缺失self参数,属于语法错误,直接运行会报错;
  2. logger类设计冗余,本质是工具逻辑却用实例方法实现,每个业务类都要手动调用初始化,代码重复;
  3. 虽然logging.getLogger(__name__)是单例(多次调用返回同一个logger实例),但每个类实例都执行初始化逻辑属于重复操作,毫无必要。

更优方案推荐两种:

方案1:全局初始化日志配置

在文件开头一次性完成日志配置,所有类直接使用已配置好的全局logger:

import logging
import json

# 全局初始化日志,仅执行一次
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
if not logger.hasHandlers():
    file_handler = logging.FileHandler("qwerty.log")
    stream_handler = logging.StreamHandler()
    # 直接定义logging规范的格式字符串,不要用json.dumps
    format_str = "%(asctime)s - %(levelname)s - %(message)s"
    formatter = logging.Formatter(format_str)
    file_handler.setFormatter(formatter)
    stream_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    logger.addHandler(stream_handler)

class ABC():
    def some_func(self):
        logger.info("Hi from ABC")

class XYZ(ABC):
    def some_func(self):
        logger.info("Hi from XYZ")

class zxc():
    def some_func(self):
        try:
            logger.info("Hi from ZXC")
            raise Exception
        except:
            logger.error("Some issue")

方案2:使用Mixin类

把日志初始化逻辑封装成Mixin类,需要日志功能的业务类直接继承该Mixin,避免重复代码:

import logging
import json

class LoggerMixin:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        if not self.logger.hasHandlers():
            file_handler = logging.FileHandler("qwerty.log")
            stream_handler = logging.StreamHandler()
            format_str = "%(asctime)s - %(levelname)s - %(message)s"
            formatter = logging.Formatter(format_str)
            file_handler.setFormatter(formatter)
            stream_handler.setFormatter(formatter)
            self.logger.addHandler(file_handler)
            self.logger.addHandler(stream_handler)

class ABC(LoggerMixin):
    def __init__(self):
        super().__init__()
    def some_func(self):
        self.logger.info("Hi from ABC")

class XYZ(ABC):
    def __init__(self):
        super().__init__()  # 自动继承LoggerMixin的日志初始化逻辑
    def some_func(self):
        self.logger.info("Hi from XYZ")

class zxc(LoggerMixin):
    def __init__(self):
        super().__init__()
        self.abc = ABC()
    def some_func(self):
        try:
            self.logger.info("Hi from ZXC")
            raise Exception
        except:
            self.logger.error("Some issue")

问题3:logger.error的日志可在控制台显示,但无法写入日志文件qwerty.log,无报错信息,请问原因是什么?

核心问题是日志格式字符串处理错误:你把格式字典用json.dumps()转成了JSON字符串,但logging.Formatter需要的是占位符格式的字符串(比如%(asctime)s),而非JSON文本。

举个例子,你生成的format_str是"{\"timestamp\": \"%(asctime)s\"}",这个字符串被传给Formatter后,日志系统无法识别%(asctime)s作为占位符,最终写入文件的内容要么是空的,要么只显示静态JSON结构(不会替换实际时间等动态内容)。

另外还需排查:

  1. 程序是否拥有qwerty.log文件的写入权限;
  2. 相对路径是否正确(确认程序运行的工作目录);
  3. 代码语法错误是否导致FileHandler未被正确创建。

修正方式:去掉json.dumps(),直接定义符合logging规范的格式字符串,示例:

format_str = "%(asctime)s - %(levelname)s - %(message)s"
formatter = logging.Formatter(format_str)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:50:29