来自多个模块的Python日志问题

11 投票
1 回答
12927 浏览
提问于 2025-04-17 01:44

我有三个Python模块。

LogManager.py
Runner.py
Other.py

Runner.py是整个流程中的第一个主要模块,从这个模块里会调用Other.py中的一些函数。

所以,在Runner.py里面,我有一个调用LogManager.py的函数。

logger = LogManager.get_log()

从那里,我可以进行简单的日志记录,比如说logger.critical("OHNOES")

我希望get_log这个函数能做的事情,类似于单例模式,也就是说,如果日志记录器还没有被设置,它就会设置好并返回这个记录器;如果已经设置好了,就直接返回这个记录器。

这是LogManager.py的内容:

import logging

def get_log():
    logger = logging.getLogger('PyPro')
    logger.setLevel(logging.DEBUG)

    # create file handler which logs even debug messages
    fh = logging.FileHandler('pypro.log')
    fh.setLevel(logging.DEBUG)

    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(logging.WARNING)

    # create formatter and add it to the handlers
    fhFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    chFormatter = logging.Formatter('%(levelname)s - %(filename)s - Line: %(lineno)d - %(message)s')
    fh.setFormatter(fhFormatter)
    ch.setFormatter(chFormatter)

    # add the handlers to logger
    logger.addHandler(ch)
    logger.addHandler(fh)

    logger.info("-----------------------------------")
    logger.info("Log system successfully initialised")
    logger.info("-----------------------------------")

    return logger

如你所见,每次调用LogManager.get_log()时,它都会尝试设置一个新的日志。其实,我对发生的事情有点困惑……

Runner.py在它的主方法中调用get_log函数。

Other.py在全局范围内调用get_log(在导入之后,任何函数之前)

结果是我所有的日志都会被记录两次,因为为记录器创建了两个处理器。

我错过了什么简单的方法,让get_log函数返回同一个日志实例呢?

1 个回答

16

logging模块已经为你实现了一个单例模式——当你调用logger.getLogger(name)时,如果这个日志记录器还没有被创建,它会自动创建一个并返回给你。虽然这和你问的不是完全一样,但我建议你把get_log()改名为setup_log(),因为它的作用就是这样。然后你只需要在代码开始的时候调用一次setup_log()。之后,当你真正需要使用日志记录器时,只需用logging.getLogger(),它会返回已经配置好的日志记录器。

撰写回答