python日志处理程序中setLevel的意义是什么?
假设我有以下代码:
import logging import logging.handlers a = logging.getLogger('myapp') h = logging.handlers.RotatingFileHandler('foo.log') h.setLevel(logging.DEBUG) a.addHandler(h) # The effective log level is still logging.WARN print a.getEffectiveLevel() a.debug('foo message') a.warn('warning message')
我期望在处理程序上设置logging.DEBUG
会导致debugging级别的消息被写入日志文件。 但是,这会打印30个有效级别(相当于logging.WARNING
,默认值),并且只将warn
消息logging到日志文件中,而不是debugging消息。
看起来处理程序的日志级别正在被丢弃,例如,它被默默地忽略了。 这让我感到奇怪,为什么在处理程序上有setLevel
?
它允许更好的控制。 默认情况下,根logging器具有WARNING
级别设置,这意味着它不会打印较低级别的消息(不pipe处理程序的级别如何设置!)。 但是,如果将根logging器的级别设置为DEBUG
,则确实将消息发送到日志文件:
import logging import logging.handlers a = logging.getLogger('myapp') a.setLevel(logging.DEBUG) # set root's level h = logging.handlers.RotatingFileHandler('foo.log') h.setLevel(logging.DEBUG) a.addHandler(h) print a.getEffectiveLevel() a.debug('foo message') a.warn('warning message')
现在,图像,你想添加一个新的处理程序,不loggingdebugging信息。 你可以通过简单地设置处理程序的日志级
import logging import logging.handlers a = logging.getLogger('myapp') a.setLevel(logging.DEBUG) # set root's level h = logging.handlers.RotatingFileHandler('foo.log') h.setLevel(logging.DEBUG) a.addHandler(h) h2 = logging.handlers.RotatingFileHandler('foo2.log') h2.setLevel(logging.WARNING) a.addHandler(h2) print a.getEffectiveLevel() a.debug('foo message') a.warn('warning message')
现在,日志文件foo.log
将包含这两个消息,而文件foo2.log
将仅包含警告消息。 你可能对只有错误级别消息的日志文件感兴趣,然后只需添加一个Handler
,并将其级别设置为logging.ERROR
,使用同一个Logger
所有内容。
您可能会认为Logger
日志logging级别是针对给定日志logging程序及其处理程序的哪些消息“有趣”的全局限制。 logging器之后考虑的消息被发送到处理程序,处理程序执行它们自己的过滤和logging过程。
在Python日志logging中有两个不同的概念:logging器logging的级别和处理程序实际激活的级别。
当进行日志调用时,基本上发生的是:
if self.level <= loglevel: for handler in self.handlers: handler(loglevel, message)
然后每个处理程序然后会调用:
if self.level <= loglevel: # do something spiffy with the log!
如果你想要一个真实世界的演示,你可以看看Django的configuration设置 。 我将在这里包含相关的代码。
LOGGING = { #snip 'handlers': { 'null': { 'level': 'DEBUG', 'class': 'logging.NullHandler', }, 'console':{ 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'filters': ['special'] } }, 'loggers': { #snip 'myproject.custom': { # notice how there are two handlers here! 'handlers': ['console', 'mail_admins'], 'level': 'INFO', 'filters': ['special'] } } }
因此,在上面的configuration中,只有日志getLogger('myproject.custom').info
及以上版本才会被logging处理。 当发生这种情况时,控制台将输出所有的结果(它会输出所有的东西,因为它被设置为DEBUG
级别),而mail_admins
logging器将会发生所有的ERROR
, FATAL
和CRITICAL
。
我想一些不是Django的代码也可以帮助:
import logging.handlers as hand import logging as logging # to make things easier, we'll name all of the logs by the levels fatal = logging.getLogger('fatal') warning = logging.getLogger('warning') info = logging.getLogger('info') fatal.setLevel(logging.FATAL) warning.setLevel(logging.WARNING) info.setLevel(logging.INFO) fileHandler = hand.RotatingFileHandler('rotating.log') # notice all three are re-using the same handler. fatal.addHandler(fileHandler) warning.addHandler(fileHandler) info.addHandler(fileHandler) # the handler should log everything except logging.NOTSET fileHandler.setLevel(logging.DEBUG) for logger in [fatal,warning,info]: for level in ['debug','info','warning','error','fatal']: method = getattr(logger,level) method("Debug " + logger.name + " = " + level) # now, the handler will only do anything for *fatal* messages... fileHandler.setLevel(logging.FATAL) for logger in [fatal,warning,info]: for level in ['debug','info','warning','error','fatal']: method = getattr(logger,level) method("Fatal " + logger.name + " = " + level)
这导致:
Debug fatal = fatal Debug warning = warning Debug warning = error Debug warning = fatal Debug info = info Debug info = warning Debug info = error Debug info = fatal Fatal fatal = fatal Fatal warning = fatal Fatal info = fatal
再次注意,当日志处理程序设置为DEBUG
时, info
如何logginginfo
, warning
, error
和fatal
info
,但当处理程序设置为FATAL
,突然间只有FATAL
消息将其传递到文件。
处理程序代表不同的受众logging事件。 处理程序上的级别用于控制特定受众看到的输出的详细程度,以及除了logging器上设置的任何级别之外的行为。 logging器上的级别用于控制从应用程序或库的不同部分进行logging的总体冗长度。
请参阅此图了解如何处理日志事件的更多信息: