【问题标题】:incremental output with subprocess.PIPEsubprocess.PIPE 的增量输出
【发布时间】:2011-06-06 20:42:21
【问题描述】:

我正在使用subprocess 模块从另一个应用程序运行命令我知道您可以执行以下操作

import subprocess

app = subprocess(args, stdout=subprocess.PIPE)
out, err = app.communicate()
print out

我希望输出显示为最后一个大斑点。想法?

【问题讨论】:

    标签: python subprocess stdout


    【解决方案1】:

    问题可能是您在子进程中运行的命令缓冲了它的输出:在这种情况下,在 Blender 的回答中,process.stdout.read(1) 不会返回,直到子进程的输出缓冲区填满,导致它被刷新,因此被父进程看到。

    有关缓冲如何影响事物的更多信息,请参阅 this answerthis one

    这里有一些脚本来说明:

    # spew.py
    import sys
    import time
    
    for i in range(10):
        print 'Message no. %d' % i
        #sys.stdout.flush()
        time.sleep(1)
    

    # runspew.py
    import subprocess
    import time
    
    start = time.time()
    p = subprocess.Popen(['python', 'spew.py'], stdout=subprocess.PIPE)
    data = p.stdout.read(1)
    print 'Elapsed time to first byte read: %.2f' % (time.time() - start)
    data = p.stdout.read()
    print 'Elapsed time to last byte read: %.2f' % (time.time() - start)
    p.wait()
    

    现在,将两个脚本放在同一个目录中并运行python runspew.py。你会看到这样的东西:

    Elapsed time to first byte read: 10.05
    Elapsed time to last byte read: 10.05
    

    现在,从sys.stdout.flush() 中删除spew.py 中的评论,然后再次执行python runspew.py。您现在将看到如下内容:

    Elapsed time to first byte read: 0.02
    Elapsed time to last byte read: 10.04
    

    注意runspew.py 没有改变:只有作为子进程运行的程序才改变。如果您正在运行的程序无法无缓冲运行(或频繁刷新),那么您必须使用expect/unbuffer,如我链接到的其他答案中所述。

    【讨论】:

      【解决方案2】:

      我曾经做过一个 Python shell 实现,所以这是我用来运行命令的代码。它运行 wgetnano 很好,所以我认为代码会满足您的需求:

        process = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
      
        while True:
          output = process.stdout.read(1)
      
          if output == '' and process.poll() != None:
            break
      
          if output != '':
            sys.stdout.write(output)
            sys.stdout.flush()
      

      基本上,你必须直接写到stdout

      【讨论】:

      • 完整变量有什么用?
      • 关键是调用sys.stdout.flush(),否则Python会继续缓冲输出。
      • @dustyprogrammer,我实际上并不知道 XD。我检查了我的代码,这是唯一一次使用它。是时候切断一个残留的器官了……
      猜你喜欢
      • 2012-11-15
      • 2016-01-01
      • 2017-02-05
      • 1970-01-01
      • 2014-03-31
      • 2016-02-13
      • 2014-11-23
      • 2020-04-13
      • 2015-10-09
      相关资源
      最近更新 更多