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_adminslogging器将会发生所有的ERRORFATALCRITICAL

我想一些不是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如何logginginfowarningerrorfatal info ,但当处理程序设置为FATAL ,突然间只有FATAL消息将其传递到文件。

处理程序代表不同的受众logging事件。 处理程序上的级别用于控制特定受众看到的输出的详细程度,以及除了logging器上设置的任何级别之外的行为。 logging器上的级别用于控制从应用程序或库的不同部分进行logging的总体冗长度。

请参阅此图了解如何处理日志事件的更多信息:

在这里输入图像描述