我正在使用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')
    

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

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

    关于python - 为什么logger.info()仅在调用logging.info()之后出现?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57115395/

    10-16 06:08