多模块Python日志问题

11

我有三个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(),它将返回已配置好的记录器。


不幸的是,我一直在使用Other.py的主函数作为验证测试,我希望能够这样做。如果我只是调用logging.getLogger(),那么我将无法进行验证测试,因为我没有设置日志(日志将在Runner.py中设置)。 - Colton Phillips

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接