简体   繁体   English

Python:contextlib.redirect_stdout有时无法实时运行

[英]Python: contextlib.redirect_stdout sometimes doesn't work in real time

I am using Python3.5 on Ubuntu. 我在Ubuntu上使用Python3.5。 The following script creates a file out and fills it with more and more lines of "Hello": 以下脚本创建一个文件out并用越来越多的“ Hello”行填充它:

import contextlib
with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')

However, if I make a tiny modification by adding a call to time.sleep() , the file out stays empty: 但是,如果我通过添加对time.sleep()的调用进行了微小的修改,则文件out保持空白:

import contextlib
import time
with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')
        time.sleep(1)

If I further change the code by turning the loop into a finite loop, it fills out but only in a lump at the end of the loop. 如果我通过将循环变成有限循环来进一步更改代码,则它会填充out但只会在循环结束时一次出现。

Can anyone reproduce this and explain it? 谁能复制并解释它?

This is caused by output buffering. 这是由输出缓冲引起的。 This is an interesting case given the use of contextlib , but the underlying issue is with the open('out', 'w') statement. 考虑到使用contextlib ,这是一个有趣的情况,但是潜在的问题是open('out', 'w')语句。

To prevent output buffering, you can set the buffering argument to 0 if you're using Python 2: 为了防止输出缓冲,如果您使用的是Python 2,可以将buffering参数设置为0

import contextlib
import time

with contextlib.redirect_stdout(open('out','w', 0)):
    while True:
        print 'Hello'
        time.sleep(1)

Alternatively, the file contents will be written once the context manager closes the file (or once the buffered content exceeds a certain size). 或者,一旦上下文管理器关闭文件(或一旦缓冲的内容超过特定大小),就将写入文件内容。

If you're using Python 3, then you can't have unbuffered text I/O (kindly pointed out in the comments). 如果您使用的是Python 3,那么您就不能拥有无缓冲的文本I / O(请在注释中指出)。 However, flushing stdout at the end of each loop should have the desired effect: 但是,在每个循环结束时刷新stdout应该具有所需的效果:

import contextlib
import time
import sys

with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')
        sys.stdout.flush()
        time.sleep(1)

I bet this has been asked before but I can't find a good duplicate. 我敢打赌,这已经被问过了,但我找不到一个很好的副本。

This is caused by output buffering. 这是由输出缓冲引起的。 When stdout goes to a terminal, it is line buffered, meaning output is sent from your program to the terminal every time a "\\n" is encountered. 当stdout进入终端时,它是行缓冲的,这意味着每次遇到"\\n"时,输出将从程序发送到终端。 But when stdout refers to a file, it is block buffered. 但是,当stdout引用文件时,它将被块缓冲。 This means actual output is generated only when the buffer grows full (or when you explicitly flush it or when the handle is closed). 这意味着仅在缓冲区变满(或显式刷新缓冲区或关闭句柄)时才生成实际输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM