从根继承的python记录器级别默认情况下设置为警告 [英] python logger level inherited from root set to warning by default

查看:50
本文介绍了从根继承的python记录器级别默认情况下设置为警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我在开头定义了一个类似于以下内容的记录器:

In my program I define a logger at the beginning that looks similar to this:

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)

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

I then have multiple files that are called from my main program. In order for them to work correctly I need to do the following:

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?这是在带有不同模块的程序包中创建日志记录模块的最佳方法还是有更好的解决方案?

Why is the default level for all modules that I import set to warning. Why do I have to set the level again to DEBUG for each of them when they import my root logger with log = logging.getLogger(name)? Is this the best way to create a logging module accross a package with different modules or is there a better solution?

推荐答案

让我们先看看Handler.setLevel

Let's start by looking at what Handler.setLevel does:

将此处理程序的阈值设置为lvl.严重程度低于lvl的日志消息将被忽略.创建处理程序后,该级别将设置为NOTSET(这将导致处理所有消息).

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毫无意义(除非您定义自己的日志级别),因为没有比调试更严重的消息了.因此,这意味着处理程序将不会忽略任何消息.

Any messages less severe than lvl are ignored. Effectively, setting it to DEBUG is meaningless (unless you define your own log levels), because there is no less severe message than debug. So, that means that the handler won't ignore any messages.

setLevel 是正确的主意,但是您在错误的对象上调用它.查看 Logger.setLevel :

setLevel is the right idea, but you're calling it on the wrong object. Look at Logger.setLevel:

将此记录器的阈值设置为lvl.严重程度低于lvl的日志消息将被忽略.创建记录器时,该级别设置为NOTSET(当记录器是根记录器时,将处理所有消息;如果记录器是非根记录器,则将委派给父级).请注意,根记录器的创建级别为警告.

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.

委派给父级"一词意味着,如果记录器具有NOTSET级别,则遍历其祖先记录器链,直到找到非NOTSET级别的祖先或达到根.

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.

如果发现某个祖先的级别不是NOTSET,那么该祖先的级别将被视为祖先搜索开始的记录器的有效级别,并用于确定如何处理日志事件.

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.

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

You're creating the children right, but they're all children of the root logger. They're level is set to NOTSET, and it propagates up to the root, whose default value is WARNING. Consequently, you don't see any messages.

TL; DR:解决方案很简单:在记录器上而不是在处理程序上设置级别.以下代码应满足您的要求:

TL;DR: The solution is simple: set the level on the logger, not the handler. The following code should do what you need:

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)

一旦这样做,创建孩子时就不需要 setLevel 调用.

Once you do that, you shouldn't need the setLevel call when making the children.

哦,还要回答您的其他问题:这正是您应该使用日志记录库的方式.(实际上,我只是将所有内容都记录到root记录器中,因为我不需要您开发的那种粒度,但是当您有理由支持时,您将按照自己的意愿进行操作.)

Oh, and to answer your other questions: this is exactly the way you're supposed to use the logging library. (I actually just log everything to the root logger, because I don't need the kind of granularity you developed, but when you have a case for it, you're doing it just as you should.)

编辑:显然,setLevel在根记录器上似乎不起作用.相反,在访问根记录器之前,必须设置basicConfig.在 logging.basicConfig 中设置级别将满足您的需要(至少在我的测试中有效).请注意,此操作与从多个模块登录中给出的示例匹配,因此应该解决您的问题.

Evidently, setLevel doesn't seem to work on the root logger. Instead, before accessing the root logger, you have to set basicConfig. Setting the level in logging.basicConfig will do what you need (at least, it worked in my tests). Note, doing this matches the example given in Logging from multiple modules, so should solve your problem.

这篇关于从根继承的python记录器级别默认情况下设置为警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆