【问题标题】:immediate piping with python使用 python 立即管道
【发布时间】:2012-03-18 05:04:32
【问题描述】:

我有两个文件,第一个是 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,但真正发生的是它在3 之后同时打印startedended秒。有没有办法得到我想要的行为?谢谢

【问题讨论】:

    标签: python unix pipe


    【解决方案1】:

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

    #!/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,则结束。

    【讨论】:

      【解决方案2】:

      好问题。这比它应该的要难一点。

      问题确实在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.
      

      【讨论】:

        【解决方案3】:

        有两个问题:

        1. print "something" in ./foo 不会刷新其 stdout 缓冲区,如果它被重定向(在这种情况下是到管道),即当 stdout is not connected a tty-like device 例如,到交互式控制台时
        2. for line in sys.stdin: 可能会尝试一次读取几行

        您可以按如下方式修复它:

        $ PYTHONUNBUFFERED=1 ./foo | ./bar
        

        ./bar:

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

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

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

        【讨论】:

          猜你喜欢
          • 2019-12-16
          • 1970-01-01
          • 2016-07-21
          • 2018-11-28
          • 1970-01-01
          • 2020-09-14
          • 1970-01-01
          • 1970-01-01
          • 2021-07-29
          相关资源
          最近更新 更多