首页 文章

Python记录多个模块 Logger 不在主程序外工作

提问于
浏览
6

我的目标是从多个模块进行日志记录,而只在一个地方配置 Logger - 在主程序中 . 如this answer所示,应该包括

logging.config.fileConfig('/path/to/logging.conf')

在主程序中,然后在所有其他模块中包括

logger = logging.getLogger(__name__)

我相信这就是我在下面所做的,但我得到了意想不到的行为 .

c.py

# c.py
import logging
import logging.config
import d

logging.config.fileConfig("logging.conf")
logger = logging.getLogger(__name__)

logger.warning('logging from c')
d.foo()

d.py

# d.py
import logging

logger = logging.getLogger(__name__)

# this will print when d is imported
logger.warning('logging from d on import')

def foo():
    # this does not print
    logger.warning("logging from d on call foo()")

输出

$ python c.py
logging from d on import
logging from c

我除了之外,是 d.foo()c.py 中执行时,将从 d 记录一条消息,但事实并非如此 . 这很令人困惑,因为当从 d 中的模块级别调用 Logger 时,它会将一条消息记录到控制台,但是当从 foo() 内部调用时它不会 .

配置文件

[loggers]
keys=root

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(message)s
datefmt=

进一步分析

所以我注意到,如果我删除该行

logging.config.fileConfig("logging.conf")

c.py ,然后从 d.foo() 日志记录按预期工作 . 所以配置文件中有一些错误,或者由于我提供的配置文件导致 d.py 中的 Logger 搞砸了 .

问题

  • 为什么从模块级别调用时会从 d 记录消息,而不是从 d.foo() 内部调用?

  • 如何才能实现从多个模块进行日志记录的目标,同时仅在主程序中配置日志记录?

2 回答

  • 2

    问题在于这样的事实

    import d
    

    来之前

    logging.config.fileConfig("logging.conf")
    

    正如@davidejones所指出的那样 . 这是 why:

    docs中所述,当调用 logging.config.fileConfig() 时,其默认行为是禁用任何现有 Logger . 因此,当 import d 发生时, loggerd 初始化,然后当 logging.config.fileConfig() 被调用时, d 中的 logger 被禁用,这就是我们在调用 d.foo() 时没有看到任何记录的原因 .

    解决方案

    logging.config.fileConfig() 接受一个参数 disable_existing_loggers ,默认为 True . 使用

    logging.config.fileConfig("logging.conf", disable_existing_loggers=False)
    

    输出变成了

    >>> python c.py
    logging from d on import
    logging from c
    logging from d on call foo()
    

    正如所料 .

  • 8

    我认为d的导入是在 Logger 的配置之前发生的,所以做这样的事情可能会给你想要的东西?

    # c.py
    import logging
    import logging.config
    
    logging.config.fileConfig("logging.conf")
    logger = logging.getLogger(__name__)
    
    import d
    
    
    logger.warning('logging from c')
    d.foo()
    

    它给了我这些结果

    logging from d on import
    logging from c
    logging from d on call foo()
    

    EDIT

    查看代码可能更有意义的是有一个单独的文件来进行日志记录设置,然后你在主文件中导入一次,其他模块将拥有它然后它看起来不那么混乱 . 所以也许有这样的 logsetup.py

    import logging
    import logging.config
    
    logging.config.fileConfig("logging.conf")
    

    然后c.py看起来像这样,但仍然给出相同的结果

    # c.py
    import logsetup
    import logging
    import d
    
    logger = logging.getLogger(__name__)
    
    logger.warning('logging from c')
    d.foo()
    

相关问题