为什么控制台日志记录器与print函数不同步?

4

当我尝试使用print和控制台记录器显示消息时,发现以下令人惊讶的行为:

import logging

for i in range(1, 10):
    print("Hello")
logging.warning("Hello world")

# Possible result:
Hello
WARNING:root:Hello world
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello

# Expected result:
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
WARNING:root:Hello world

这怎么可能呢?返回日志之前,记录器(无论是文件还是控制台)不应该保证写入其输出流吗?

记录包括线程并在主循环之外工作。 启动两个线程(主循环+记录)以获取可能的输出。 - dsgdfg
你知道这是在哪里记录的吗? - Erwin Mayer
1
我也在寻找这种行为。因此,我添加了一个临时解决方法,使每次调用 print() 都刷新 stdout,这似乎能改善情况。但仍然有很多时候,在日志输出之后执行的 print() 输出之后显示日志输出。我无法相信在 Python 中没有相对简单的方法来配置记录器与 print() 同步。 - Michael Burr
2个回答

1
这是您提出的几个不同问题。首先,这个陈述。
logging.Formatter('{asctime} {name} {levelname:8s} {message}', style='{')

没有效果,因为您正在实例化Formatter,然后丢弃结果。 您需要将格式化程序分配给Handler,该处理程序添加到Logger。 所有这些都在Python stdlib documentation中有记录。

其次,在您的示例中有两个不同的输出流 - print写入sys.stdout,而logging.warning(没有其他配置)写入sys.stderr。 这些流如何复用到单个控制台上并不明确定义,并取决于如何设置I / O缓冲区,您的操作系统和其他因素。


抱歉,我的代码中忘记删除格式化程序了。 - Erwin Mayer

1
这个解决方案对我有用:https://dev59.com/Y6Pia4cB1Zd3GeqPsQp5#72628419,在basicConfig()调用中将日志流设置为sys.stdout: logging.basicConfig(stream=sys.stdout, format=fmt, level=logging.INFO) 正如https://dev59.com/Y6Pia4cB1Zd3GeqPsQp5#56559936所解释的那样,默认情况下,记录器将数据记录到sys.stderr,而print则将数据打印到sys.stdout。但是,sys.stderr和sys.stdout不同步。也可以使用sys.stdout来记录日志以解决此问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接