2011-11-01 52 views
3
$ 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,而下开始打印的时候了:为什么即使在刷新和使用-u时,python仍然会缓存stdout?

$ cat script.py - | cat 

害得我以为缓冲并非来自猫。

我设法得到它的工作做:

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

如下解释:Streaming pipes in Python,但我不明白为什么如预期前解决方案不起作用。

回答

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

如果输出到管道,cat会默认阻止缓冲。所以当你在cat命令中包含 - (stdin)时,它会在输出任何内容之前等待EOF(你的ctrl-D关闭标准输入流)或8K(可能)数据。

如果将cat命令更改为“cat script.py |”你会发现它可以按照你的预期工作。另外,如果您将8K的注释添加到script.py的末尾,它也会立即将其打印出来。

编辑:

以上是错误的。 :-)

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

+0

我编辑了我的问题,解释它为什么似乎不是来自猫本身。 –

+0

你的改变没有什么区别......它是第一只缓冲的猫,因为输出到了管道。改变管道后的水槽不会改变任何东西。您可以通过简单地执行“cat script.py - ”来看到它,并且看到它会立即输出script.py,因为它将转到终端而不是管道。 –

+0

也许我的例子并不清楚,但我认为它表明,第一只猫不缓冲,因为script.py的内容在EOF发送给第一只猫之前显示。 –

相关问题