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

Col*_*ips 6 python logging singleton

我有3个python模块。

LogManager.py
Runner.py
Other.py
Run Code Online (Sandbox Code Playgroud)

Runner.py是事件链中的第一个主要模块,并且从该模块内部Other.py调用函数。

因此,在内部,Runner.py我有一个函数调用LogManager.py

logger = LogManager.get_log()
Run Code Online (Sandbox Code Playgroud)

从那里,我可以制作简单的日志,例如 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
Run Code Online (Sandbox Code Playgroud)

如您所见,LogManager.get_log()将在每次调用日志时尝试设置日志。真的,我对正在发生的事情有些困惑...

Runner.py在其main方法中调用get_log函数。Other.py在全局范围内调用get_log(在导入之后,而不是在任何函数中)

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

使get_log函数以其他方式返回同一日志的实例的最简单方法是什么?

Dav*_*d Z 6

logging模块已经为您实现了单例模式-调用时logger.getLogger(name),它将创建记录器(如果尚未创建)并返回它。尽管这不是正是你问什么,我会建议只是重新命名get_log()setup_log(),因为这是它做什么。然后,您只需setup_log()在代码开头调用一次即可。然后,当您实际需要记录器时,只需使用logging.getLogger()它,它将返回已配置的记录器。