python日志处理程序中的setLevel有什么意义?
假设我有以下代码:python日志处理程序中的setLevel有什么意义?,python,logging,Python,Logging,假设我有以下代码: 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(
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
会导致调试级别的消息写入日志文件。但是,这会为有效级别打印30(默认值等于logging.WARNING
),并且只将warn
消息记录到日志文件,而不是调试消息
处理程序的日志级别似乎被丢弃在地板上,例如,它被默默地忽略。这让我想知道,为什么处理程序上有
setLevel
它允许更精细的控制。默认情况下,根记录器设置了警告
级别,这意味着它不会打印级别较低的消息(无论处理程序的级别如何设置!)。但是,如果将根记录器的级别设置为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')
现在,您需要添加一个不记录调试信息的新处理程序。
只需设置处理程序日志记录级别即可完成此操作:
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
将只包含警告消息。您可能对只包含错误级别消息的日志文件感兴趣,然后只需添加一个处理程序
,并将其级别设置为logging.error
,所有操作都使用相同的记录器
您可以将
记录器日志记录级别视为对给定记录器及其处理程序“感兴趣”的消息的全局限制。记录器随后考虑的消息被发送到处理程序,处理程序执行自己的过滤和日志记录过程。在Python日志记录中,有两个不同的概念:记录器日志记录的级别和处理程序实际激活的级别
调用日志时,基本上发生的是:
if self.level <= loglevel:
for handler in self.handlers:
handler(loglevel, message)
因此,在上面的配置中,只有getLogger('myproject.custom').info
及更高版本的日志才会被处理以进行日志记录。当这种情况发生时,控制台将输出所有结果(它将输出所有结果,因为它被设置为DEBUG
level),而mail\u admins
logger将对所有ERROR
s、FATAL
s和CRITICAL
s进行记录
我想一些不是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
调试警告=警告
调试警告=错误
调试警告=致命
调试信息=info
调试信息=警告
调试信息=错误
调试信息=致命
致命的
致命警告=致命
致命信息=致命信息
再次注意,当日志处理程序设置为调试时,info
、warning
、error
和fatal
是如何记录的,但是,当处理程序设置为FATAL
时,突然只有FATAL
消息进入文件。处理程序代表记录事件的不同受众。处理程序上的级别用于控制特定受众看到的输出的详细程度,并作为记录器上设置的任何级别的补充。Logger上的级别用于控制来自应用程序或库的不同部分的日志记录的总体详细程度
有关如何处理日志事件的更多信息,请参阅:
规则
当且仅当
handler.level <= message.level
&&
logger.level <= message.level
参考:
换句话说
如果记录器设置为警告
,则处理程序是否具有更详细的设置并不重要。当它到达处理程序时,它已经被过滤了
一个完整的例子
给
output for `logger_info.info('hello')`
INFO message for logger_info handled by handler_info: hello
INFO message for logger_info handled by handler_debug: hello
output for `logger_info.debug('bonjour')`
# nothing, because message.level < logger.level
output for `logger_debug.info('hola')`
INFO message for logger_debug handled by handler_info: hola
INFO message for logger_debug handled by handler_debug: hola
output for `logger_debug.debug('ciao')`
DEBUG message for logger_debug handled by handler_debug: ciao
# nothing from handler_info, because message.level < handler.level
'logger_info.info('hello')的输出`
处理程序处理的记录器信息的信息消息\u INFO:hello
记录器的信息消息\u处理程序处理的信息\u调试:您好
“logger_info.debug('bonjour')的输出`
#没有,因为message.level
好问题,但为了连贯性,如果您正在测试a.getEffectiveLevel
,a.setLevel
比h.setLevel
更有意义。在这种情况下,处理程序没有getEffectiveLevel
命令,因此最佳做法是设置较低级别的根记录器,并通过处理程序级别控制日志记录。我说的对吗?这不是“最佳实践”,只是做任何其他事情都是毫无用处的。如果处理程序的级别是DEBUG,但记录器只发送错误,那么处理程序当然只会接收(并传递)错误。那么,人们不禁要问,为什么根记录器的默认日志级别不是DEBUG
或0
,实际上,因为如果你不知道这个“把戏”,那么你只会像操作一样搔头,我想知道为什么你的日志消息没有被打印出来。@Christoph我相信是因为DEBUG
是用来调试应用程序的,因此只有在开发人员调试应用程序时才会出现。将默认级别设置为“警告”可避免在实际用户使用应用程序时,某些缺少的配置会导致打印噪音。换句话说:显示低级消息需要用户的干预。(显然这只是一种观点,人们也可以提出相反的观点)。好吧,但在这种情况下,据我所知,我至少希望INFO
是默认值,然后……不管怎样,正如你所说的,观点。你好@Vinay Sajip!因此,如果省略处理程序的级别,它默认为什么?我正在使用dictConfig
方法为我的应用程序全局执行一些自定义日志配置,我已经阅读了文档,它说处理程序的级别是可选的,但没有说明默认值。我也不能从ab中推断出来
handler.level <= message.level
&&
logger.level <= message.level
Level | Numeric value
---------|--------------
CRITICAL | 50
ERROR | 40
WARNING | 30
INFO | 20
DEBUG | 10
NOTSET | 0
import logging
handler_info = logging.StreamHandler()
handler_info.setLevel("INFO")
handler_info.setFormatter(logging.Formatter(
f"%(levelname)s message for %(name)s handled by handler_info: %(message)s"))
handler_debug = logging.StreamHandler()
handler_debug.setLevel("DEBUG")
handler_debug.setFormatter(logging.Formatter(
f"%(levelname)s message for %(name)s handled by handler_debug: %(message)s"))
logger_info = logging.getLogger('logger_info')
logger_info.setLevel("INFO")
logger_info.addHandler(handler_info)
logger_info.addHandler(handler_debug)
logger_debug = logging.getLogger('logger_debug')
logger_debug.setLevel("DEBUG")
logger_debug.addHandler(handler_info)
logger_debug.addHandler(handler_debug)
print()
print("output for `logger_info.info('hello')`")
logger_info.info("hello")
print()
print("output for `logger_info.debug('bonjour')`")
logger_info.debug("bonjour")
print()
print("output for `logger_debug.info('hola')`")
logger_debug.info("hola")
print()
print("output for `logger_debug.debug('ciao')`")
logger_debug.debug("ciao")
print()
output for `logger_info.info('hello')`
INFO message for logger_info handled by handler_info: hello
INFO message for logger_info handled by handler_debug: hello
output for `logger_info.debug('bonjour')`
# nothing, because message.level < logger.level
output for `logger_debug.info('hola')`
INFO message for logger_debug handled by handler_info: hola
INFO message for logger_debug handled by handler_debug: hola
output for `logger_debug.debug('ciao')`
DEBUG message for logger_debug handled by handler_debug: ciao
# nothing from handler_info, because message.level < handler.level