为什么即使在刷新和使用 -u 时,python 也会继续缓冲标准输出?
$ 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中的流管道,但我不明白为什么前一个解决方案不能按预期工作。
$ cat script.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
sys.stdout.flush()
$ cat script.py - | python -u script.py
The output is right but it only starts printing once I hit Ctrl-D whereas the following starts printing right away :
$ cat script.py - | cat
which led me to think that the buffering does not come from cat.
I managed to get it working by doing :
for line in iter(sys.stdin.readline, ""):
as explained here : Streaming pipes in Python, but I don't understand why the former solution doesn't work as expected.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Python 手册页揭示了您问题的答案:
那就是:文件对象迭代器的内部缓冲是罪魁祸首(并且它不会随 -u 一起消失)。
Python manpage reveals the answer to your question:
That is: file-object iterators' internal buffering is to blame (and it doesn't go away with -u).
如果输出到管道,cat 默认会阻止缓冲。因此,当您在 cat 命令中包含 - (stdin) 时,它会在输出任何内容之前等待获取 EOF(您的 ctrl-D 关闭 stdin 流)或 8K(可能)数据。
如果将 cat 命令更改为“cat script.py |”你会发现它按照你的预期工作。
另外,如果你在 script.py 的末尾添加 8K 注释,它也会立即打印出来。
编辑:
以上是错误的。 :-)
事实证明 file.next() (由文件迭代器使用,即文件中的行)有一个隐藏的预读缓冲区,readline() 不使用该缓冲区,它只是读取一个字符,直到看到一个字符为止。换行符或 EOF。
cat does block buffering by default if output is to a pipe. So when you include - (stdin) in the cat command, it waits to get EOF (your ctrl-D closes the stdin stream) or 8K (probably) of data before outputting anything.
If you change the cat command to "cat script.py |" you'll see that it works as you expected.
Also, if you add 8K of comments to the end of script.py, it will immediately print it as well.
Edit:
The above is wrong. :-)
It turns out that file.next() (used by file iterators, ie. for line in file) has a hidden read-ahead buffer that is not used by readline(), which simply reads a character until it sees a newline or EOF.