从库模块进行Python日志记录

12 投票
1 回答
10564 浏览
提问于 2025-04-27 22:55

我正在尝试在我的Python库模块中设置通用的日志记录,这样它们就可以使用调用模块中配置的日志记录器,而不需要硬编码日志记录器的名称。我看到很多例子是在调用模块中使用logging.basicConfig(),然后在库模块中调用logging.debug(),但是当我配置自己的StreamHandler时,这种方法就不管用了。我到底哪里做错了呢?

这是我的调用模块:

import logging, logging.handlers
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
consolehandler = logging.StreamHandler()
consoleformatter = logging.Formatter('[%(name)s] %(levelname)s %(message)s')
consolehandler.setFormatter(consoleformatter)
logger.addHandler(consolehandler)
import libmodule

def run():
    logger.info("message from calling module")
    libmodule.say("message from library module")

我在libmodule.py中尝试了这个:

import logging

def say(msg):
    logging.info(msg)

还有这个:

import logging
logger = logging.getLogger()

def say(msg):
    logger.info(msg)

但是在这两种情况下,当我调用run()时,我得到的输出是:

[callingmodule] INFO message from calling module

而我原本期待的是:

[callingmodule] INFO message from calling module
[callingmodule] INFO message from library module
暂无标签

1 个回答

8

这是因为在第一个情况下,你是通过名字获取一个日志记录器,而在第二个情况下,你只是使用 getLogger(),它返回的是根日志记录器。根日志记录器和你自定义的日志记录器不一样,也没有安装你自定义的流处理器。

更简单的方法是按照文档中的指导来做,文档可以在这里找到:

'多次使用相同名字调用 getLogger() 总是会返回同一个 Logger 对象的引用。'

换句话说,如果你在两个地方都使用 getLogger('my_common_name'),那么它们都会自动指向同一个日志记录器,即使你在一个地方对它进行了自定义。

补充:如果你想从父级捕获日志记录器,那么你可以在你的库中这样做:

# In libmodule

_log = None

def initLogger(logger=None):
    global _log
    if logger != None:
        _log = logger
    else:
        import logging
        _log = logging.getLogger()

# Later in the module
def say(message):
    _log.info(message)

然后在你的父模块中:

# In the parent module
mylog = a logger i set up

import libmodule
libmodule.initLogger(mylog)

这样应该能让它们都指向同一个日志记录器。

撰写回答