Python 類的建構函式中初始化日誌記錄器後,導致日誌被重複列印

飞仔FeiZai發表於2024-11-25

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 引數不要重複,特別是在類的建構函式中。

相關文章