为什么即使在刷新和使用 -u 时,python 也会继续缓冲标准输出?

发布于 2024-12-13 02:44:22 字数 515 浏览 1 评论 0原文

$ 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青瓷清茶倾城歌 2024-12-20 02:44:22

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 一起消失)。

Python manpage reveals the answer to your question:

   -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.

That is: file-object iterators' internal buffering is to blame (and it doesn't go away with -u).

写下不归期 2024-12-20 02:44:22

如果输出到管道,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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文