【问题标题】:Alternative to subprocess.Popen.communicate() for streaming用于流式传输的 subprocess.Popen.communicate() 的替代方案
【发布时间】:2017-02-09 22:31:08
【问题描述】:

如果我使用subprocess.Popen,我可以使用communicate() 进行小输出。

但如果子流程要花费大量时间并产生大量输出,我想将其作为流数据访问。

有没有办法做到这一点? Python 文档说

警告:使用communicate() 而不是.stdin.write.stdout.read.stderr.read 以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致的死锁。

我真的很想以类似文件的对象的形式访问进程输出:

with someMagicFunction(['path/to/some/command','arg1','arg2','arg3']) as outpipe:
   # pass outpipe into some other function that takes a file-like object

但不知道该怎么做。

【问题讨论】:

    标签: python io subprocess


    【解决方案1】:

    communicate 是启动后台线程读取stdoutstderr 的便捷方法。您可以自己阅读stdout,但您需要弄清楚如何处理stderr。如果您不关心错误,可以添加参数stderr=open(os.devnull, 'wb') 或文件stderr=open('somefile', 'wb')。或者,创建您自己的后台线程来进行读取。原来shutil已经有了这样的功能,所以我们可以使用它。

    import subprocess
    import threading
    import shutil
    import io
    
    err_buf = io.BytesIO()
    
    proc = subprocess.Popen(['ls', '-l'],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    err_thread = threading.Thread(target=shutil.copyfileobj, 
        args=(proc.stderr, err_buf))
    err_thread.start()
    for line in proc.stdout:
        print(line.decode('utf-8'), end='')
    retval = proc.wait()
    err_thread.join()
    print('error:', err_buf.getvalue())
    

    【讨论】:

      猜你喜欢
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2014-04-09
      相关资源
      最近更新 更多