我正在使用Python 3.6.4。我首先遇到了一个忽略logger.setLevel(logging.INFO)
的问题,并遇到了this answer,这使我感到困惑,并引发了这个问题。
鉴于以下代码,
片段1
>>> import logging
>>> logger = logging.getLogger('foo') # named logger
>>> logger.setLevel(logging.INFO)
>>> logger.info('1')
>>> logging.info('2') # prints nothing
>>> logger.info('3')
INFO:foo:3
片段2>>> import logging
>>> logger = logging.getLogger() # no name
>>> logger.setLevel(logging.INFO)
>>> logger.info('1')
>>> logging.info('2') # printed
INFO:root:2
>>> logger.info('3')
INFO:root:3
最佳答案
如您所指出的,这些片段之间的区别在于如何获取logger
对象:
logger = logging.getLogger('foo')
logger = logging.getLogger()
关键是,在第二种情况下,您将获得“root”记录器。另一方面,在第一种情况下,您得到的是名为
foo
的根的“sublogger”。现在,让我们逐步进行。
logger.setLevel(logging.INFO)
在这里,您可以设置记录器的级别。在第一种情况下,您将设置记录器
foo
的级别。创建时,新的记录器没有级别,因此它们会处理每条消息。在这里,您是说只处理严重性为INFO
或更高的消息。但是,在第二种情况下,logger
是根记录器。令人困惑的是,与新记录器不同,根记录器的默认级别为WARN
,因此,除非您对其进行更改,否则不会处理低于该级别的任何内容。因此,在此行之后:WARN
级别,而foo
记录器设置为INFO
级别。 INFO
级别。 logger.info('1')
第一条记录的行。在这两种情况下,您都具有相同的行为。该消息为
INFO
,并且logger
设置为该严重性,因此将处理该消息。但是,您没有在logger
中设置任何处理程序,因此该消息实际上不执行任何操作。logging.info('2')
现在,这更有趣。此处重要的是
logging.info
实际执行的操作,这与您调用根记录程序对象的info
方法不同:因此,如果没有为根记录器注册任何处理程序,则此函数将自行创建控制台处理程序。因此,由根记录器或子记录器收到的任何消息现在都将打印到控制台。但是,在第一种情况下,事实证明根记录器仍具有其默认的严重性过滤器
WARN
,因此已注册控制台处理程序,但实际上忽略了该消息。但是,在第二种情况下,您将根记录程序的严重性级别设置为INFO
,因此消息由控制台处理程序处理和打印。logger.info('3')
希望现在应该有意义。现在,您已将控制台处理程序附加到根记录器。在第一种情况下,
logger
是foo
记录器,其严重性设置为INFO
,因此将处理消息,并且由于它是根记录器的子记录器,因此由为该记录器注册的控制台处理程序将其打印出来。在第二种情况下,您仅登录到根记录器,该记录器的严重性为INFO
,并且注册了控制台处理程序。请注意,在第一种情况的最后一行中,即使根记录器的严重性级别为
foo
,由WARN
记录器处理的消息也由在根记录器中注册的处理程序处理。日志处理程序不负责按严重性进行过滤,这是由记录器本身完成的,因此,一旦记录器决定了应该处理的消息,它将由其所有处理程序以及来自父记录器的处理程序进行处理。这是一项非常有用的功能,因为它使您可以拥有较高的系统级别日志级别,而对于您更感兴趣的特定模块(例如,用于调试或简单地报告)则具有较低的日志级别。关于python - 为什么logger.info()仅在调用logging.info()之后出现?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57115395/