如前所述https://stackoverflow.com/a/4150322/1526342。当记录到子记录器时,它会将消息传递给其父记录,并且其父记录将消息传递给根记录器。 现在考虑以下示例
import logging
import logging.handlers
child_logger = logging.getLogger(__name__)
f = logging.Formatter(
fmt='%(asctime)s; %(name)s; % (filename)s:%(lineno)d:%(message)s',
datefmt="%Y-%m-%d %H:%M:%S")
handler = logging.handlers.RotatingFileHandler('/tmp/info.log',
encoding='utf8',
maxBytes=500000000,
backupCount=5)
handler.setFormatter(f)
child_logger.setLevel(logging.INFO)
child_logger.addHandler(handler)
child_logger.info('1 + 1 is %d', 1+1)
child_logger
应该报告回根记录器,而不是将输出打印到child_logger的日志文件。
我很困惑。
答案 0 :(得分:2)
如this logging flow chart所示,记录器将日志记录传递给自己的处理程序和到父记录器对象。尝试将处理程序添加到父记录器,您将看到正在处理日志记录。
答案 1 :(得分:0)
在这种情况下,您的'child_logger'是您的根记录器。如果你这样初始化它:
logger = getLogger('root')
child_logger = getLogger('root.child')
child_logger
是logger
的孩子,定义如下:
该名称可能是一个以句点分隔的层次结构值,例如foo.bar.baz(例如,它也可能只是普通的foo)。在分层列表中较低的记录器是列表中较高的记录器的子项。例如,给定一个名为foo的记录器,名称为foo.bar,foo.bar.baz和foo.bam的记录器都是foo的后代。记录器名称层次结构类似于Python包层次结构,如果使用推荐的构造logging.getLogger(
__name__
)在每个模块的基础上组织记录器,则与其相同。那是因为在模块中,__name__
是Python包命名空间中的模块名称。
如果您不希望孩子传播,您可以设置logger.propagate
= False
。
此外,如果您只希望将某些级别写入您的子记录器文件(即仅调试),但您希望更高级别仍然传播,则可以创建处理程序的子类,如我的所在:
from logging import DEBUG, INFO, WARN, ERROR, CRITICAL, handlers
class DebugRotatingFileHandler(handlers.RotatingFileHandler):
def __init__(self, filename, mode, maxBytes, backupCount, encoding, delay):
super(DebugRotatingFileHandler, self).__init__(
self, filename, mode, maxBytes, backupCount, encoding, delay)
def emit(self, record):
if record.levelno != DEBUG:
return
super(DebugRotatingFileHandler, self).emit(self, record)
(是的,我知道可以做一些改进,这是旧代码。)
例如,执行debug_logger.info("Info Message")
将不会向debug_logger的指定文件打印任何内容,但是,如果将root_logger
的级别设置为info或debug,则会将其打印在其文件中。我使用它进行调试日志记录,同时仍保留让记录器进行错误消息调用并将其打印到根日志的能力。