未通过使用 fileConfig 配置的处理程序记录 Python 根记录器消息

Cla*_*ine 5 python logging configuration-files python-2.7

问题:

给定一个日志配置和一个使用该配置的记录器,我看到来自配置日志处理程序的脚本的日志消息,但不是来自分配了相同处理程序的根记录器。

细节:

(使用 Python 2.7)

我有一个my_mod实例化记录器的模块。my_mod具有my_command使用该记录器记录一些消息的功能。my_mod存在于库中my_lib,所以我不想用任何处理程序配置记录器;按照建议,我想将日志处理留给使用my_mod. my_mod好像:

import logging

LOGGER = logging.getLogger(__name__)

def my_command():
    LOGGER.debug("This is a log message from module.py")
    print "This is a print statement from module.py"
Run Code Online (Sandbox Code Playgroud)

我还有一个 python 脚本my_script.py,它使用my_mod.my_command. my_script.py实例化一个记录器,在这种情况下,我确实配置了处理程序和格式化程序。my_script.py配置处理程序和格式化程序使用fileConfig和一个配置文件一起存在my_script.py

import os
import logging
import logging.config
from my_mod.module import my_command

logging.config.fileConfig('{0}/logging.cfg'.format(
    os.path.dirname(os.path.realpath(__file__))))
LOGGER = logging.getLogger(__name__)

LOGGER.debug("This is a log message from script.py")
my_command()
Run Code Online (Sandbox Code Playgroud)

据我所知,我的配置文件似乎设置正确......

[loggers]
keys=root,script

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_script]
level=DEBUG
handlers=consoleHandler
qualname=script
propagate=0

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

[formatter_simpleFormatter]
format=%(asctime)s [%(levelname)s] %(name)s: %(message)s
datefmt=
Run Code Online (Sandbox Code Playgroud)

...但是当我运行时,我my_script.py只得到来自 的日志行my_script.py,而不是来自my_mod.my_command. my_command不过,我知道这是有效的,因为my_command调试日志语句后的打印语句成功打印到控制台:

20:27 $ python script.py 
2015-06-15 20:27:54,488 [DEBUG] __main__: This is a log message from script.py
This is a print statement from module.py
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

注:使用调试的例子显示,但即使我把logging.cfg指定level=DEBUG(我也尝试level=NOTSET)为根记录和通话LOGGER.info(message)my_command,没有被记录到控制台。

dhk*_*hke 6

一个潜在的问题是您在设置记录器配置之前导入模块。这样,模块在设置日志记录之前请求记录器。

查看 afileConfig()的文档,后续记录到预先获得的记录器失败的原因是其disable_existing_loggers参数的默认值:

logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)
Run Code Online (Sandbox Code Playgroud)

如果您将代码更改为

logging.config.fileConfig(
    '{0}/logging.cfg'.format(os.path.dirname(os.path.realpath(__file__))),
    disable_existing_loggers=False
)
Run Code Online (Sandbox Code Playgroud)

问题应该消失了。

请注意,只有在配置文件中未明确命名时,现有记录器才会被禁用。例如:

import logging
import logging.config

lFooBefore = logging.getLogger('foo')
lScriptBefore = logging.getLogger('script')
logging.config.fileConfig('logger.ini')

lFooBefore.debug('Does not log')
lScriptBefore.debug('Does log')
logging.getLogger('foo').debug('Does also not log')
logging.getLogger('bar').debug('Does log')
Run Code Online (Sandbox Code Playgroud)

不知道为什么默认值disable_existing_loggers是这样的......