Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么logger.info()只在调用logging.info()后出现?_Python_Python 3.x_Logging - Fatal编程技术网

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

Python 为什么logger.info()只在调用logging.info()后出现?,python,python-3.x,logging,Python,Python 3.x,Logging,我正在使用Python 3.6.4。我第一次遇到的问题是,logger.setLevel(logging.INFO)被忽略,这让我感到困惑,并引发了这个问题 根据下面的代码 1。为什么logging.info('2')在代码段2中打印,而不是在1中打印?(难道logging.info()不是模块级函数吗?为什么命名记录器会影响此调用?) 2。为什么打印的是logger.info('3'),而不是logger.info('1')? 片段1 片段2 正如您所指出的,代码片段之间的区别在于如何获取lo

我正在使用Python 3.6.4。我第一次遇到的问题是,
logger.setLevel(logging.INFO)
被忽略,这让我感到困惑,并引发了这个问题

根据下面的代码

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

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

片段1 片段2
正如您所指出的,代码片段之间的区别在于如何获取
logger
对象:

logger = logging.getLogger('foo')
logger = logging.getLogger()
关键是,在第二种情况下,您将获得“根”记录器。另一方面,在第一种情况下,您将得到一个名为
foo
的根的“子日志”

现在,让我们一步一步走

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

  • 在第一个代码段中,根记录器设置为
    WARN
    级别,而
    foo
    记录器设置为
    INFO
    级别
  • 在第二个代码段中,根记录器设置为
    INFO
    级别
第一条记录的线路。在这两种情况下,您都有相同的行为。该消息为
INFO
,并且
logger
设置为该严重性,因此将处理该消息。但是,
logger
中没有设置任何处理程序,因此实际上没有对消息进行任何处理

logging.info('2')
现在这更有趣了。这里重要的是
logging.info
实际上做了什么,这与调用根记录器对象的
info
方法不同:

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

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

logger.info('3')
希望这现在能有意义。现在您有了一个连接到根记录器的控制台处理程序。在第一种情况下,
logger
foo
记录器,其严重性被设置为
INFO
,因此消息被处理,并且由于它是根记录器的子记录器,因此它由为该记录器注册的控制台处理程序打印。在第二种情况下,您只是登录到根记录器,它具有
INFO
严重性和注册的控制台处理程序

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

请参阅该帖子上的:

如果您没有使用任何处理程序配置日志记录(如在文章中-您只为日志记录程序配置了一个级别,但在任何地方都没有处理程序),您将获得一个内部处理程序“最后手段”,该处理程序设置为仅输出
警告级别的消息(没有其他格式)

您的级别当前低于
警告
,因此不会输出。这会随着对
basicConfig()
的调用而改变,您可以/应该显式地执行该操作,否则直到从
logging.info
(或其他方便函数之一)调用它时才会处理它

文件规定:

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

logging.info('2')
logger.info('3')