为什么logger.info()仅在调用logging.info()之后出现?

时间:2019-07-19 15:18:38

标签: python python-3.x logging

我正在使用Python 3.6.4。我首先遇到一个问题,其中logger.setLevel(logging.INFO)被忽略,并遇到this answer,这使我感到困惑,并引起了这个问题。

给出以下代码,

  

1。为什么logging.info('2')会在代码段2中打印而不是在代码1中打印?logging.info()不是模块级功能吗?为什么命名记录器会影响此调用?)

     

2。为什么logger.info('3')而不是logger.info('1')被打印?

片段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

2 个答案:

答案 0 :(得分:6)

正如您所指出的,这些片段之间的区别在于如何获取logger对象:

logger = logging.getLogger('foo')
logger = logging.getLogger()

关键是,在第二种情况下,您将获得“ root”记录器。另一方面,在第一种情况下,您获得的根的“子记录器”名为foo

现在,让我们逐步进行。

logger.setLevel(logging.INFO)

在这里设置记录器的级别。在第一种情况下,您要设置记录器foo的级别。创建时,新的记录器没有级别,因此它们会处理每条消息。在这里,您是说只处理严重性为INFO或更高的消息。但是,在第二种情况下,logger是根记录器。令人困惑的是,与新记录器不同,根记录器的默认级别为WARN,因此,除非您进行更改,否则不会处理低于该级别的任何内容。因此,在此行之后:

  • 在第一个代码段中,根记录器设置为WARN级别,而foo记录器设置为INFO级别。
  • 在第二个片段中,根记录器设置为INFO级别。
logger.info('1')

第一条记录的行。在这两种情况下,您的行为相同。该消息为INFO,并且logger设置为该严重性,因此该消息得到处理。但是,您在logger中没有设置任何处理程序,因此该消息实际上什么也没做。

logging.info('2')

现在,这更有趣。这里重要的是logging.info实际执行的操作,这与调用根记录程序对象的info方法不同:

  

在根记录器上记录严重性为“ INFO”的消息。如果记录仪有   没有处理程序,请调用basicConfig()以添加具有预定义的控制台处理程序   格式。

因此,如果没有为根记录器注册任何处理程序,则此函数将自行创建控制台处理程序。因此,由根记录器或子记录器收到的任何消息现在都将打印到控制台。但是,在第一种情况下,事实证明根记录器仍具有其默认的严重性过滤器WARN,因此已注册控制台处理程序,但实际上忽略了该消息。但是,在第二种情况下,您将根记录程序的严重性级别设置为INFO,因此消息由控制台处理程序处理和打印。

logger.info('3')

希望现在应该有意义。现在,您已将控制台处理程序附加到根记录器。在第一种情况下,loggerfoo记录器,其严重性设置为INFO,因此,该消息被处理,并且由于它是根记录器的子记录器,因此它是由注册该控制台的控制台处理程序打印。在第二种情况下,您只是登录到具有INFO严重性和已注册控制台处理程序的root记录器。

请注意,在第一种情况的最后一行中,由foo记录器处理的消息由在根记录器中注册的处理程序处理,即使根记录器的严重性级别为WARN 。日志处理程序不负责按严重性进行过滤,这由记录器本身完成,因此,一旦记录器决定应该处理一条消息,它将由其所有处理程序以及来自父记录器的处理程序进行处理。这是一项非常有用的功能,因为它使您可以拥有较高的系统级别日志级别,而对于您更感兴趣的特定模块(例如,用于调试或仅进行报告)则具有较低的日志级别。

答案 1 :(得分:2)

请参阅该帖子上的accepted answer

  

如果您未使用任何处理程序配置日志记录(如您的帖子中所示-您仅为记录器配置一个级别,但未在任何地方配置处理程序),则将获得一个内部处理程序“不得已”在set.seed(24) userMaster <- data.frame(desire = rep(LETTERS[1:4], each = 5), user_id = sample(1:5, 20, replace = TRUE), source = sample(letters[1:3], 20, replace = TRUE)) 级别仅输出消息(没有其他格式)。

您的级别当前小于 WARNING,因此不会输出。这可能会随着您对WARNING的调用而发生变化,您可能/应该明确地进行此操作,否则直到从basicConfig()(或其他便利功能之一)中调用它之前,它都不会得到处理。

文档遵循以下规定:

  

注意:上面的模块级便捷功能(委托给root记录器)调用logging.info以确保至少有一个处理程序可用。因此,除非在启动线程之前已在根记录器中添加至少一个处理程序,否则在2.7.1和3.2之前的Python版本中,不应在线程中使用它们。在Python的早期版本中,由于basicConfig()中存在线程安全性缺陷,这可能(在极少数情况下)导致将处理程序多次添加到root记录器中,进而可能导致同一事件的多个消息