帮助我理解python的日志记录模块及其处理程序

时间:2011-09-22 18:03:51

标签: python logging

我真的很想念python的日志记录模块。

在下面的代码中,我创建了一个logger对象(log)并添加了两个处理程序。一个用 'INFO'级别和'WARNING'级别。它们都应该打印到stdout。我希望拨打log.info(msg) 将在我的标准输出中生成msg的一个副本,并调用log.warn(msg)结果 两份msg印在我的标准上。这是代码:

import logging
import sys


logging.basicConfig()
log = logging.getLogger('myLogger')
log.handlers = []
h1 = logging.StreamHandler(sys.stdout)
h1.level = logging.INFO
h1.formatter = logging.Formatter('H1 H1 %(message)s ')
h2 = logging.StreamHandler(sys.stdout) 
h2.level = logging.WARNING
h2.formatter = logging.Formatter('H2 H2 %(message)s')
log.addHandler(h1)
log.addHandler(h2)

print 'log.level == %s'%logging.getLevelName(log.level)
print 'log.info'
log.info('this is some info')
print 'done'
print 'log.warn'
log.warn('this is a warning')
print 'done'

输出对我来说真的很奇怪。 .info电话会产生视觉效果。 但是,调用warn会导致两个msg打印到stdout(这是正常的),但也会打印一个副本到stderr(为什么?)。这是上面代码的输出。请注意此输出中最后一行的格式。此行打印到stderr。

log.level == NOTSET
log.info
done
log.warn
H1 H1 this is a warning 
H2 H2 this is a warning
done
WARNING:myLogger:this is a warning

所以我的问题是:

  1. 为什么我对info的调用导致没有输出,尽管h1的级别设置为INFO?
  2. 为什么我对warn的调用导致额外输出到stderr?

2 个答案:

答案 0 :(得分:7)

您需要了解两件事:

  1. 根记录器的初始化级别为WARNING

    如果记录器的级别低于记录器的级别,则会丢弃到达记录器的任何日志消息。如果未设置记录器的级别,则将从其父记录器获取其“有效级别”。因此,如果根记录器的级别为WARNING,则所有记录器的默认有效级别为WARNING。如果不进行其他配置,则将丢弃级别低于该级别的所有日志消息。

  2. 当您致电basicConfig()时,系统会自动在根记录器上设置StreamHandler,以打印到标准错误流。

    当你的程序打印出它的日志消息时,实际上有三个处理程序:你添加的两个处理程序,它们有自己的级别,还有一个来自打印出任何消息的系统没有被其记录器拒绝。这就是你得到这条线的原因

    WARNING:myLogger:this is a warning
    

    它来自系统记录器。它不会对INFO级别的消息执行此操作,因为如前所述,根记录器配置为默认拒绝这些消息。

    如果您不想要此输出,请不要致电basicConfig()

  3. 进一步阅读:http://docs.python.org/howto/logging.html

答案 1 :(得分:3)

实际上有五个级别的日志记录:调试,信息,警告,错误和严重。我看到,当您设置记录器时,您没有明确设置您的级别 - 我相信如果未设置级别,记录器可能会默认警告。

至于为什么它会多次打印以进行警告,我相信这是因为你创建了两个处理信息&警告。发生的事情是记录器的严重性从警告级联下降 - >信息 - > debug,为每个调用处理程序。由于您的级别设置为警告,因此将忽略信息处理程序。另外,我认为警告消息通常写入sys.stderr。

尝试以下方法:

logging.basicConfig(level=logging.INFO)

另见: