来自班级记录器的重复消息

时间:2019-04-21 04:45:18

标签: python python-3.x logging

我的班级构造了一个以 init ()中的班级命名的记录器。现在,当我记录一条消息时,对于到目前为止已创建的该类的每个实例,我都会得到一条消息的副本。如何避免这种重复?

我还担心这可能只是一个更深层次问题的征兆-这是一种浪费性的内存管理方法,可一次实例化几百个类吗?有没有更明智的方式来处理跨多个类的日志记录?

尽管下面的代码是问题的简单再现,但是实际的代码是非常模块化的,并且每个类可以通过各种不同的应用程序以许多不同的方式使用。每个类都可以用作由其定义的main()方法调用的独立类,也可以从另一个类或三个或四个主要应用程序之一中调用。日志记录方法需要考虑到这种模块化。

import logging

class person:
    def __init__(self,name):
        self.name = name
        logger = logging.getLogger('person logger')
        logger.setLevel(logging.DEBUG)
        ch = logging.StreamHandler()
        formatter = logging.Formatter('%(name)s - %(message)s')
        ch.setFormatter(formatter)
        logger.addHandler(ch)

        logger.info(f'{self.name} exists')


if __name__ == '__main__':

    for name in ["Alice", "Bob", "Carlos"] :
        a = person(name)

预期结果:

person logger - Alice exists
person logger - Bob exists
person logger - Carlos exists

实际结果:

person logger - Alice exists
person logger - Bob exists
person logger - Bob exists
person logger - Carlos exists
person logger - Carlos exists
person logger - Carlos exists

1 个答案:

答案 0 :(得分:4)

使用if logger.handlers检查是否已经有处理程序。或者,您每次创建该person对象时都要添加处理程序。

基本上:

import logging

class person:
    def __init__(self,name):
        self.name = name
        logger = logging.getLogger('person logger')
        logger.setLevel(logging.DEBUG)
        if not logger.handlers:
            ch = logging.StreamHandler()
            formatter = logging.Formatter('%(name)s - %(message)s')
            ch.setFormatter(formatter)
            logger.addHandler(ch)

        logger.info(f'{self.name} exists')


if __name__ == '__main__':

    for name in ["Alice", "Bob", "Carlos"] :
        a = person(name)

此外,大多数情况下,我们不是为类而是为模块创建记录器。

对于一个大型项目,创建一个log_helper模块,其中可能包含初始化函数:

def getLogger(name):
    logger = logging.getLogger(name)
    # do some initialization...
    # like adding handlers
    return logger

在每个模块的顶部获取记录器:

# person.py  Module person

import log_helper

logger = log_helper.getLogger("person") # or whatever you want

# just use this logger...