为什么即使在刷新和使用-u时python也会继续缓冲stdout?

时间:2011-11-01 22:46:59

标签: python stdout pipe buffering

$ cat script.py
import sys

for line in sys.stdin:
    sys.stdout.write(line)
    sys.stdout.flush()

$ cat script.py - | python -u script.py

输出正确,但只有在按下Ctrl-D后才开始打印,而以下内容立即开始打印:

$ cat script.py - | cat

这让我觉得缓冲不是来自猫。

我设法让它工作:

for line in iter(sys.stdin.readline, ""):

如下所述:Streaming pipes in Python,但我不明白为什么前一种解决方案无法按预期工作。

2 个答案:

答案 0 :(得分:4)

Python手册页显示了您问题的答案:

   -u     Force stdin, stdout and stderr to be totally unbuffered.  On systems where it matters, also put stdin, stdout and stderr in binary mode.  Note that
          there  is  internal  buffering  in  xreadlines(),  readlines()  and file-object iterators ("for line in sys.stdin") which is not influenced by this
          option.  To work around this, you will want to use "sys.stdin.readline()" inside a "while 1:" loop.

那就是:文件对象迭代器的内部缓冲是责备(并且它不会随着-u而消失。)

答案 1 :(得分:1)

如果输出到管道,

cat会默认阻止缓冲。因此,当您在cat命令中包含 - (stdin)时,它会在输出任何内容之前等待获取EOF(您的ctrl-D关闭stdin流)或8K(可能)数据。

如果将cat命令更改为“cat script.py |”你会发现它按你的预期运作。

另外,如果你在script.py的末尾添加了8K的注释,它也会立即打印出来。

编辑:

以上是错误的。 : - )

事实证明,file.next()(由文件迭代器使用,即用于文件中的行)有一个隐藏的预读缓冲区,readline()不使用它,只读取一个字符直到它看到换行或EOF。