【问题标题】:Python: contextlib.redirect_stdout sometimes doesn't work in real timePython:contextlib.redirect_stdout 有时不能实时工作
【发布时间】:2017-09-12 08:12:10
【问题描述】:

我在 Ubuntu 上使用 Python3.5。以下脚本创建了一个文件out,并用越来越多的“Hello”行填充它:

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

但是,如果我通过添加对time.sleep() 的调用进行微小修改,则文件out 保持为空:

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

如果我通过将循环变为有限循环来进一步更改代码,它会填充out,但只会在循环结束时一次性填充。

谁能重现并解释一下?

【问题讨论】:

    标签: python io-redirection buffering


    【解决方案1】:

    这是由输出缓冲引起的。考虑到contextlib 的使用,这是一个有趣的案例,但根本问题在于open('out', 'w') 语句。

    为防止输出缓冲,如果您使用的是 Python 2,可以将 buffering argument 设置为 0

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

    或者,一旦上下文管理器关闭文件(或缓冲的内容超过一定大小),文件内容将被写入。

    如果您使用的是 Python 3,则不能使用无缓冲文本 I/O(请在 cmets 中指出)。但是,在每个循环结束时刷新stdout 应该会产生预期的效果:

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

    【讨论】:

    • 请注意,这在 Python3 中不起作用,请参阅 stackoverflow.com/questions/27067713/…
    • 很好,抱歉,我应该正确测试我的答案。更新为 Python 3 提供合适的解决方法。
    【解决方案2】:

    我敢打赌,以前有人问过这个问题,但我找不到合适的副本。

    这是由输出缓冲引起的。当 stdout 进入终端时,它是行缓冲的,这意味着每次遇到 "\n" 时都会将输出从您的程序发送到终端。但是当 stdout 引用一个文件时,它是块缓冲的。这意味着只有当缓冲区变满时(或者当您显式刷新它或关闭句柄时)才会生成实际输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多