如何在Python中创建一个非root记录器。

4
我正在尝试在一个子Python模块中使用logging.getLogger('child')创建一个非根记录器,但是我收到了一个错误消息“找不到适合“child”记录器的处理程序”。
我想让父模块记录到父日志文件。父模块将创建子模块的实例,我希望子模块能够编写自己的子日志文件,而不会将其消息传播到父日志文件。
以下是我为父模块准备的代码(由用户执行):
#!/usr/bin/env python

import logging, child

logging.basicConfig( filename='parent.log' )
logging.warning( 'test log from parent' )

c = child.run()

以下是子模块:

import logging
class run:
  def __init__(self):
    logging.basicConfig( filename = 'child.log' )
    childLogger = logging.getLogger( __name__ )
    childLogger.propagate = False
    childLogger.warning( 'this is a log from the child' )

期望的输出结果是有两个文件:parent.log(包含父模块中的1个警告行)和child.log(包含子模块中的一个警告行)。

实际输出结果是:只有一个来自父模块的警告行被打印到parent.log文件中,而没有child.log文件——子日志消息没有被记录在任何地方。

请问我错过了什么?谢谢!

1个回答

4
替换
logging.basicConfig(filename='child.log')
childLogger = logging.getLogger(__name__)

在您的子模块中使用:
childLogger = logging.getLogger(__name__)
childLogger.addHandler(logging.FileHandler('child.log'))

或者,您可以使用dictConfigfileConfig在一个地方配置日志记录。从文档中来看,basicConfig有什么问题呢?引用文献如下:此函数如果根记录器已经为其配置了处理程序,则不执行任何操作。因此,基本调用在子模块中没有效果,因为第一个调用(在父模块中)已经配置了根记录器。通过将子记录器的传播设置为false,子记录器的日志条目不会转发到根记录器,因此您会收到“找不到处理程序”的警告。

我来详细说明一下fileConfig,它提供了很大的灵活性。对于你的模块,你可以创建一个名为logging.ini的文件:

[loggers]
keys=root,child

[handlers]
keys=logfile,logfile_child

[formatters]
keys=default

# loggers

[logger_root]
level=INFO
handlers=logfile

[logger_child]
level=INFO
handlers=logfile_child
qualname=child
propagate=0

# handlers

[handler_logfile]
class=FileHandler
formatter=default
args=('parent.log',)

[handler_logfile_child]
class=FileHandler
formatter=default
args=('child.log',)

# formatters

[formatter_default]
format=%(asctime)s [%(module)s:%(lineno)d] %(levelname)s %(message)s
datefmt=

然后,在您的应用程序中的某个地方,您只需要调用 fileConfig

import logging.config

logging.config.fileConfig('logging.ini')

这样配置日志只需在一个地方完成,更容易添加其他记录器、更改日志级别等。

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