gpt4 book ai didi

从 root 继承的 python 记录器级别默认设置为警告

转载 作者:太空狗 更新时间:2023-10-29 23:54:30 24 4
gpt4 key购买 nike

在我的程序中,我在开始时定义了一个类似于此的记录器:

def start_logger():
fh = logging.handlers.RotatingFileHandler('logger.log',
maxBytes=1000000,
backupCount=100)
fh.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)

fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'

ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'

fh.setFormatter(logging.Formatter(fh_fmt))
ch.setFormatter(logging.Formatter(ch_fmt))

root = logging.getLogger()
root.addHandler(fh)
root.addHandler(ch)

然后我有多个文件从我的主程序中调用。为了让它们正常工作,我需要执行以下操作:

import logging
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.debug("This debug message is ounly output when I set the level again to debug for this file. Otherwise the the log level for this file is WARNING.")

为什么我导入的所有模块的默认级别都设置为警告。当他们使用 log = logging.getLogger(name) 导入我的根记录器时,为什么我必须再次将级别设置为 DEBUG?这是跨具有不同模块的包创建日志记录模块的最佳方法还是有更好的解决方案?

最佳答案

让我们先看看 Handler.setLevel does 是什么:

Sets the threshold for this handler to lvl. Logging messages which are less severe than lvl will be ignored. When a handler is created, the level is set to NOTSET (which causes all messages to be processed).

任何低于 lvl 严重程度的消息都将被忽略。实际上,将其设置为 DEBUG 是没有意义的(除非您定义自己的日志级别),因为没有比 debug 更严重的消息。所以,这意味着处理程序不会忽略任何消息。

setLevel 是正确的想法,但您在错误的对象上调用它。看Logger.setLevel :

Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored. When a logger is created, the level is set to NOTSET (which causes all messages to be processed when the logger is the root logger, or delegation to the parent when the logger is a non-root logger). Note that the root logger is created with level WARNING.

The term ‘delegation to the parent’ means that if a logger has a level of NOTSET, its chain of ancestor loggers is traversed until either an ancestor with a level other than NOTSET is found, or the root is reached.

If an ancestor is found with a level other than NOTSET, then that ancestor’s level is treated as the effective level of the logger where the ancestor search began, and is used to determine how a logging event is handled.

您正在正确地创建子项,但它们都是根记录器的子项。它们的级别设置为 NOTSET,并且向上传播到根,其默认值为 WARNING。因此,您看不到任何消息。

长话短说:解决方案很简单:在记录器上设置级别,而不是处理程序。以下代码应该可以满足您的需要:

def start_logger():
fh = logging.handlers.RotatingFileHandler('logger.log',
maxBytes=1000000,
backupCount=100)

ch = logging.StreamHandler(sys.stdout)

fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'

ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'

fh.setFormatter(logging.Formatter(fh_fmt))
ch.setFormatter(logging.Formatter(ch_fmt))

logging.basicConfig(level=logging.DEBUG)
root = logging.getLogger()
root.addHandler(fh)
root.addHandler(ch)

一旦你这样做了,你就不需要在创建 child 时调用 setLevel

哦,回答你的其他问题:这正是你应该使用日志库的方式。 (实际上,我只是将所有内容记录到根记录器中,因为我不需要您开发的那种粒度,但是当您有理由这样做时,您会按照您应该做的去做。)

编辑:显然,setLevel 似乎不适用于根记录器。相反,在访问根记录器之前,您必须设置 basicConfig。在 logging.basicConfig 中设置级别将满足您的需要(至少,它在我的测试中有效)。请注意,这样做符合 Logging from multiple modules 中给出的示例,所以应该可以解决您的问题。

关于从 root 继承的 python 记录器级别默认设置为警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44783527/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com