简体   繁体   English

Python 日志记录:传播级别低于当前记录器级别的消息

[英]Python logging: propagate messages of level below current logger level

I want to log messages of a specific logger name, of a certain level and higher (say INFO and up) to a specific log handler, say a file handler, while still getting all log messages to the console.我想将特定记录器名称、特定级别和更高级别(比如INFO及以上)的消息记录到特定的日志处理程序,比如文件处理程序,同时仍然将所有日志消息发送到控制台。 Python is version 2.7. Python 是 2.7 版。

What I tried until now was to create two loggers:到目前为止,我尝试的是创建两个记录器:

  • A root logger根记录器
  • A named logger命名记录器

For the root logger, I attached a logging.StreamHandler , and set the log level to logging.DEBUG .对于根记录器,我附加了一个logging.StreamHandler ,并将日志级别设置为logging.DEBUG

Then I attached a handler to the named logger and set level to logging.INFO for that logger.然后我将一个处理程序附加到指定的记录器,并将该记录器的级别设置为logging.INFO

When I now call my module, which uses the named logger, I do not get DEBUG logs propagated to the root logger any more.当我现在调用使用命名记录器的模块时,我不再将DEBUG日志传播到根记录器。

Note: the extraLogger has a StreamHandler here to demonstrate the issue.注意:extraLogger 在这里有一个StreamHandler来演示这个问题。 In my production code I'd use a FileHandler在我的生产代码中,我会使用FileHandler

import logging

def do_logging(turn):
    logger = logging.getLogger('extra')
    logger.info('some info turn %d' % turn) 
    logger.debug('this is debug fudge turn %d' % turn)

rootLogger = logging.getLogger()
handler = logging.StreamHandler()
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s')
handler.setFormatter(rootFormatter)
rootLogger.addHandler(handler)
rootLogger.setLevel(logging.DEBUG)

do_logging(1)

extraLogger = logging.getLogger('extra')
extraHandler = logging.StreamHandler()
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s')
extraHandler.setFormatter(extraFormatter)
extraLogger.addHandler(extraHandler)
extraLogger.setLevel(logging.INFO)

do_logging(2)

Actual Output:实际 Output:

root - INFO: some info turn 1
root - DEBUG: this is debug fudge turn 1
extra - INFO: some info turn 2
root - INFO: some info turn 2

Output that I would like to have:我想要的 Output:

root - INFO: some info turn 1
root - DEBUG: this is debug fudge turn 1
extra - INFO: some info turn 2
root - INFO: some info turn 2
root - DEBUG: this is debug fudge turn 2

I suspect that a custom Filter would be helpful in this case, but I do not know how...我怀疑自定义Filter在这种情况下会有所帮助,但我不知道如何......

You could use robert's LevelFilter like this: 您可以像这样使用robert的LevelFilter

# Put the Filter on the Handler so only INFO and higher is handled
extraHandler.addFilter(LevelFilter(logging.INFO))

# Let the Logger process everything (so it can propagate records to root)
extraLogger.setLevel(logging.DEBUG)

import logging

class LevelFilter(logging.Filter):
    """
    https://stackoverflow.com/a/7447596/190597 (robert)
    """
    def __init__(self, level):
        self.level = level

    def filter(self, record):
        return record.levelno >= self.level

def do_logging(turn):
    logger = logging.getLogger('extra')
    logger.info('some info turn %d' % turn) 
    logger.debug('this is debug fudge turn %d' % turn)

rootLogger = logging.getLogger()
handler = logging.StreamHandler()
rootFormatter = logging.Formatter('root - %(levelname)s: %(msg)s')
handler.setFormatter(rootFormatter)
rootLogger.addHandler(handler)
rootLogger.setLevel(logging.DEBUG)
do_logging(1)

extraLogger = logging.getLogger('extra')
extraHandler = logging.StreamHandler()
extraFormatter = logging.Formatter('extra - %(levelname)s: %(msg)s')
extraHandler.setFormatter(extraFormatter)
extraLogger.addHandler(extraHandler)

# Put the Filter on the Handler so only INFO and higher is handled
extraHandler.addFilter(LevelFilter(logging.INFO))

# Handle everything (so it can propagate to root)
extraLogger.setLevel(logging.DEBUG)
do_logging(2)

propagate传播

If this attribute evaluates to true, events logged to this logger will be passed to the handlers of higher level (ancestor) loggers, in addition to any handlers attached to this logger.如果此属性评估为真,则记录到此记录器的事件将传递给更高级别(祖先)记录器的处理程序,以及附加到此记录器的任何处理程序。 Messages are passed directly to the ancestor loggers' handlers - neither the level nor filters of the ancestor loggers in question are considered.消息直接传递给祖先记录器的处理程序——既不考虑相关祖先记录器的级别也不考虑过滤器。

If this evaluates to false, logging messages are not passed to the handlers of ancestor loggers.如果这评估为 false,则日志记录消息不会传递给祖先记录器的处理程序。

please visit official python site for detailed discussion regarding this.请访问官方网站python 进行详细讨论。

Diabling the propagate message禁用传播消息

import logging

handler = logging.StreamHandler()

parent = logging.getLogger("parent")
parent.addHandler(handler)
child = logging.getLogger("parent.child")
child.propagate = False

child.setLevel(logging.DEBUG)
child.addHandler(handler)

child.info("HELLO")

Output: Output:

$ python3.10 propagate.py 
HELLO

Code without disabling the propagate message不禁用传播消息的代码

import logging

handler = logging.StreamHandler()

parent = logging.getLogger("parent")
parent.addHandler(handler)
child = logging.getLogger("parent.child")
#child.propagate = False

child.setLevel(logging.DEBUG)
child.addHandler(handler)


child.info("HELLO")

Output: Output:

$ python3.10 propagate.py 
HELLO
HELLO

记录器类中有一个名为“propagate”的方法似乎可以满足您的要求: http//docs.python.org/2/library/logging.html#logger-objects

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM