用python立即管道

时间:2012-03-18 05:04:32

标签: python unix pipe

我有两个文件,其中第一个是fizz

#!/usr/bin/python                                                         
import time

print 'started'
time.sleep(3)
print 'ended'

其次是吧

#!/usr/bin/python                                                         
import sys

for line in sys.stdin:
    print line

当我运行命令./fizz | ./bar时,我希望它打印started然后等待3秒并打印ended,但真正发生的是打印started和{ 3秒后同时{1}}。有没有办法达到我想要的行为?感谢

3 个答案:

答案 0 :(得分:6)

现在很明显问题出在接收方,我提出了一个我喜欢使用的替代方案:

#!/usr/bin/python                                                   
import sys 
import os

for line in iter(sys.stdin.readline, ''):
    sys.stdout.write(line) # \n included in line

iter(func, sentinel)为每次迭代调用func(),如果函数结果== sentinel则结束。

答案 1 :(得分:5)

好问题。它比它应该有点难。

问题确实在bar,特别是sys.stdin被缓冲。我尝试使用较小的缓冲区大小打开sys.stdin并使用python -u,但这不起作用。该联机帮助页有这样的说法:

   -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 xread‐
          lines(), 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.

最后这对我有用:

#!/usr/bin/python                                                   
import sys 
import os

while True:
    line = sys.stdin.readline()
    if not line:
        break
    sys.stdout.write(line) # or print, doesn't matter.

答案 2 :(得分:1)

有两个问题:

    print "something"中的
  1. ./foo如果被重定向则不会刷新其stdout缓冲区(在本例中为管道),即stdout is not connected a tty-like device,例如,交互式控制台
  2. for line in sys.stdin:可能会尝试一次读取几行
  3. 您可以按照以下方式修复:

    $ PYTHONUNBUFFERED=1 ./foo | ./bar
    

    ./bar

    #!/usr/bin/python
    import sys
    
    for line in iter(sys.stdin.readline, ''):
        print line,
    

    即,使./foo的stdout无缓冲(-u option)并按照@Eduardo Ivanec's answer中的建议逐行读取./bar中的输入。

    作为替代方案,您可以在sys.stdout.flush()中调用./foo,而不是按照@kev's answer中的建议使其stdout无缓冲。