Python 类的构造函数中初始化日志记录器后,导致日志被重复打印

Python 类的构造函数中初始化日志记录器后,导致日志被重复打印

这个问题通常是由于添加处理器到同一个日志记录器上使用了全局的日志记录器,从而导致重复的日志记录。

以下是一些常见原因以及解决方法:

问题原因

  1. 日志处理器未被正确检查或清理:
    每次实例化类时,如果给日志记录器添加了新的处理器而未清理旧处理器,会导致重复日志。

  2. 使用了全局的日志记录器:
    直接使用 logging.getLogger() 而未设置局部的日志记录器,可能导致多个实例共享处理器。


示例问题代码

import logging

class MyClass:
    def __init__(self):
        self.logger = logging.getLogger("MyClass")
        self.logger.info("Logger initialized")

# 实例化多次
a = MyClass()  # 打印一次日志
b = MyClass()  # 打印两次日志
c = MyClass()  # 打印三次日志

解决方案

1. 检查并清理处理器

在类的构造函数中动态配置日志时,可以检查是否已经添加了处理器,避免重复添加。

改进后的代码:

import logging

class MyClass:
    def __init__(self):
        self.logger = logging.getLogger("MyClass")
        if not self.logger.handlers:  # 只添加一次处理器
            handler = logging.StreamHandler()
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formatter)
            self.logger.addHandler(handler)
        self.logger.info("Logger initialized")

# 实例化多次
a = MyClass()  # 打印一次日志
b = MyClass()  # 无重复日志
c = MyClass()  # 无重复日志

2. 为每个类实例化独立的日志记录器

为每个类实例使用独立的日志记录器,并避免全局配置影响。

改进后的代码:

import logging

class MyClass:
    def __init__(self):
        self.logger = logging.getLogger(f"MyClass-{id(self)}")  # 使用唯一的日志名称
        self.logger.setLevel(logging.INFO)
        if not self.logger.handlers:  # 避免重复添加处理器
            handler = logging.StreamHandler()
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formatter)
            self.logger.addHandler(handler)
        self.logger.info("Logger initialized")

# 实例化多次
a = MyClass()  # 每个实例独立的日志
b = MyClass()
c = MyClass()

总结

要避免日志重复输出,关键是logging.getLogger()方法 name 参数不要重复,特别是在类的构造函数中。

posted @ 2024-11-25 17:26  飞仔FeiZai  阅读(31)  评论(0编辑  收藏  举报