为什么Python在使用-flushing和-u时仍然缓存stdout?
$ 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
这让我觉得,缓冲的问题并不是出在 cat 命令上。
我通过以下方法让它正常工作:
for line in iter(sys.stdin.readline, ""):
正如这里所解释的:Python 中的流管道,但我不明白为什么之前的解决方案没有按预期工作。
2 个回答
1
默认情况下,如果输出是通过管道传输,cat命令会进行块缓冲。所以当你在cat命令中加入-(标准输入)时,它会等到接收到EOF(你按下ctrl-D来关闭标准输入流)或者大约8K的数据后才会输出任何内容。
如果你把cat命令改成"cat script.py |",你会发现它按你预期的那样工作。
另外,如果你在script.py的末尾加上8K的注释,它也会立即打印出来。
编辑:
上面的说法是错的。:-)
实际上,file.next()(用于文件迭代器,比如for line in file)有一个隐藏的预读缓冲区,而readline()并没有这个,它只是读取字符直到遇到换行符或EOF。
5
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选项,这个问题也不会消失)。