为什么print()和logger对象以意外顺序流式传输到控制台输出?

shaike

我试图在使用两个记录器对象之前和之后使用打印功能,这两个记录器对象会将输出流式传输到控制台。事情是我得到了一个非常混乱的输出,它的输出顺序不正确。

我尝试将print()更改为logger_object.info(),并且按预期工作。

带有意外输出的完整代码:

import logging

# Create logger objects and set  level
loggerA = logging.getLogger()
loggerA.setLevel(logging.DEBUG)

loggerB = logging.getLogger()
loggerB.setLevel(logging.DEBUG)

# Set log output format
log_format = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s', datefmt='%m/%d/%Y - %I:%M:%S %p')

# Create a console stream handler
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(log_format)

# Add handlers to the loggers
loggerA.addHandler(stream_handler)
loggerB.addHandler(stream_handler)


def main():
    for i in range(10):
        print('Starting loop number {}'.format(i))
        loggerA.info("loop number {}".format(i))
        loggerB.info("loop number {}".format(i))
        print('Finished loop number {}'.format(i))

if __name__ == '__main__':
    main()

添加loggerC对象以用loggerC.info()替换print():

...
loggerC = logging.getLogger()
loggerC.setLevel(logging.DEBUG)
...
def main():
    for i in range(10):
        loggerC('Starting loop number {}'.format(i))
        loggerA.info("loop number {}".format(i))
        loggerB.info("loop number {}".format(i))
        loggerC('Finished loop number {}'.format(i))
...

使用print()意外输出的第一种情况是:

04/06/2019 - 10:10:34 AM - INFO - loggerA - loop number 1
Starting loop number 1
04/06/2019 - 10:10:34 AM - INFO - loggerB - loop number 1
04/06/2019 - 10:10:34 AM - INFO - loggerA - loop number 2
04/06/2019 - 10:10:34 AM - INFO - loggerB - loop number 2
Finished loop number 1
Starting loop number 2
Finished loop number 2
Starting loop number 3
Finished loop number 3
04/06/2019 - 10:10:34 AM - INFO - loggerA - loop number 3
04/06/2019 - 10:10:34 AM - INFO - loggerB - loop number 3

第二种情况是使用loggerC.info()而不是print(),这是预期的输出:

04/06/2019 - 10:12:21 AM - INFO - loggerC - Starting loop number 1
04/06/2019 - 10:12:21 AM - INFO - loggerA - loop number 1
04/06/2019 - 10:12:21 AM - INFO - loggerB - loop number 1
04/06/2019 - 10:12:21 AM - INFO - loggerC - Finished loop number 1
04/06/2019 - 10:12:21 AM - INFO - loggerC - Starting loop number 2
04/06/2019 - 10:12:21 AM - INFO - loggerA - loop number 2
04/06/2019 - 10:12:21 AM - INFO - loggerB - loop number 2
04/06/2019 - 10:12:21 AM - INFO - loggerC - Finished loop number 2
04/06/2019 - 10:12:21 AM - INFO - loggerC - Starting loop number 3
04/06/2019 - 10:12:21 AM - INFO - loggerA - loop number 3
04/06/2019 - 10:12:21 AM - INFO - loggerB - loop number 3
04/06/2019 - 10:12:21 AM - INFO - loggerC - Finished loop number 3
兰德西

您发出的问题可能是标准流的问题默认情况下print使用std::outlogger.info使用std::err这两个流都绑定到您的终端,但是它们可能具有不同的flush刷新或触发器。

这就是为什么您的输出混合在一起,函数写入不同的流,并且将它们以不同的方式刷新到终端的原因,从而导致明显的不一致结果。

更改您的第一个代码以强制logger.info使用相同的流而不是print解决问题:

import sys
stream_handler = logging.StreamHandler(sys.stdout)

现在,它返回正确的输出:

-- Starting loop number 0
04/06/2019 - 07:41:34 AM - INFO - root - loop number 0
04/06/2019 - 07:41:34 AM - INFO - root - loop number 0
-- Finished loop number 0
-- Starting loop number 1
04/06/2019 - 07:41:34 AM - INFO - root - loop number 1
04/06/2019 - 07:41:34 AM - INFO - root - loop number 1
-- Finished loop number 1
-- Starting loop number 2
04/06/2019 - 07:41:34 AM - INFO - root - loop number 2
04/06/2019 - 07:41:34 AM - INFO - root - loop number 2
-- Finished loop number 2
-- Starting loop number 3
04/06/2019 - 07:41:34 AM - INFO - root - loop number 3
04/06/2019 - 07:41:34 AM - INFO - root - loop number 3
-- Finished loop number 3

因为无论print并且logger.info无论何时在被刷新到终端的正确顺序供给相同的流,结果是正确的。

您还可以保留不同的流,并强制显式刷新std::out

def main():
    for i in range(10):
        print('-- Starting loop number {}'.format(i))
        # Force std::out stream (fed by print) to be flushed to the terminal
        # before logger feeds std::err and also flushes
        sys.stdout.flush() 
        loggerA.info("loop number {}".format(i))
        loggerB.info("loop number {}".format(i))
        print('-- Finished loop number {}'.format(i))
        sys.stdout.flush()

第二个版本也产生了预期的结果。

还请记住,logger从定义上讲不是线程安全的,print不是。如果要使用线程制作模块,则仅用于logger跟踪执行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从CMD控制台将输出流式传输到VB ListBox

inotifywait不将输出管道传输到控制台

如何将功能输入和输出从控制台传输到GUI应用程序?

将输出管道传输到文件时,为什么stderr和stdout的顺序错误?

如何将控制台输出直接管道传输到记事本?

如何通过管道将Java控制台输出传输到文件?

为什么我不能将PRINT的输出重定向到控制台?

为什么Python在print()输出之前将异常打印到控制台

为什么用逗号“”和“ +”以不同的方式记录控制台输出?

将PuTTY控制台管道传输到Python脚本

如何将 QLineEdit 值传输到控制台?

为什么控制台会覆盖输出?

控制台输出顺序错误

在添加空数组和对象时,为什么控制台会这样返回?

在没有Java Web Start的情况下,如何通过管道将Java控制台输出传输到文件?

System.out.print()不会将任何输出发送到Eclipse控制台。为什么?

将 Logger 输出复制到 production.log 和控制台以用于 Rake 任务

控制台日志不输出对象

Java Logger控制台流重复输出

IntelliJ和控制台输出颜色

eclipse控制台出现意外的中文输出

意外的BPython控制台输出行为

控制台输出中出现意外字符

XmlWriter打印到控制台时输出意外的编码

Firestore控制台日志输出中的意外行为

java.util.HashMap----看控制台,为什么打印顺序是这样的

有没有一种方法可以将长的Groovy execute()命令的输出流传输到控制台,而不是等待它完成?

从控制台C#将Cookie传输到浏览器

反复将数据从Windows服务传输到控制台应用程序