关于python:Python2.7日志级别的日志记录不起作用

Python2.7 log level of logging doesn't work

最近似乎有了一些关于python日志记录包的更改。以前的一些代码现在不起作用。我很困惑。我的python版本是python 2.7.15。

我不理解的第一个例子是,下面只打印"警告:根:来自警告的你好"。如果我理解正确,"logging.info"实际上调用根记录器,而根记录器默认为警告级别。所以第一个"信息问好"被忽略了,这很好。但是为什么第二个"信息问好"也没有打印出来呢?

1
2
3
4
5
6
import logging
logging.info("hello from info")
logging.warn("hello from warn")

logging.basicConfig(level=logging.INFO)
logging.info("hello from info")

第二个问题是处理程序和记录器的日志级别。如果我们为处理程序和记录器都设置了日志级别,那么哪个正在工作?或者,如果我们只是为处理程序设置级别呢?以下面的例子为例。我们已经为streamhandler设置了日志级别,但是"hello-from-info"不会打印到stdout。只有"来自警告的你好"(此外,它不是"警告:t:来自警告的你好")。为什么?

1
2
3
4
5
6
7
import logging
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
logger = logging.getLogger('t')
logger.addHandler(ch)
logger.info("hello from info")
logger.warn("hello from warn")


But why the second"hello from info" is also not printed?

因为

  • logging.info / warn / error / debug在引擎盖下面叫logging.basicConfig。例子:

    1
    2
    3
    4
    def info(msg, *args, **kwargs):
        if len(root.handlers) == 0:
            basicConfig()
        root.info(msg, *args, **kwargs)
  • 如果已经配置了根记录器,那么logging.basicConfig不会做任何事情。从文档中引用:


    This function does nothing if the root logger already has handlers configured for it.

  • 因此,在您的代码中,当执行logging.info("hello from info")时,根记录器配置为WARN级别。后续调用logging.basicConfig(level=logging.INFO)无效。

    经验法则:在代码中尽早配置记录器(无论是手动还是通过logging.basicConfig())。

    If we set the log level for both the handler and logger, which one is working?

    都是!日志程序级别和处理程序级别是筛选记录的两个不同阶段。logger级别定义实际传递给其处理程序的记录,而handler级别定义特定处理程序将处理哪些记录。示例:

    1
    2
    3
    4
    logger.setLevel(logging.INFO)
    handler.setLevel(logging.ERROR)
    logger.addHandler(handler)
    logger.info('spam')

    由于logger具有级别INFO,它将处理spam记录并将其传递给处理程序。但是,handler的级别是ERROR级,所以这个记录不会被处理程序处理。

    1
    2
    3
    4
    logger.setLevel(logging.WARN)
    handler.setLevel(logging.DEBUG)
    logger.addHandler(handler)
    logger.info('spam')

    现在,处理程序将处理几乎所有记录,包括spam记录,因为它的级别是INFO,因此大于DEBUG。但是,处理程序将永远不会收到要处理的spam,因为记录器不会处理它,因此不会将spam传递给它的处理程序。

    1
    2
    3
    4
    5
    6
    7
    8
    logger.setLevel(logging.INFO)
    h1 = logging.StreamHandler()
    h1.setLevel(logging.CRITICAL)
    h2 = logging.FileHandler('some.log')
    h2.setLevel(logging.DEBUG)
    logger.addHandler(h1)
    logger.addHandler(h2)
    logger.info('spam')

    现在记录器有两个处理程序,h1将记录打印到终端,h2将记录写入文件。记录器将只将级别INFO或更高的记录传递给其处理程序。但是,您将在终端中只看到级别为CRITICAL的记录,而在日志文件中看到所有记录。