在Python中,如何将多个进程与popen链接在一起,同时将中间部分结果重定向到一个字符串中

Posted

技术标签:

【中文标题】在Python中,如何将多个进程与popen链接在一起,同时将中间部分结果重定向到一个字符串中【英文标题】:In Python, how can I chain multiple processes together with popen, while redirecting intermediate partial results into a string 【发布时间】:2014-03-13 23:52:20 【问题描述】:

我一直在寻找一种在python中将多个进程链接在一起的方法,同时将一些中间进程的stderr重定向到一个字符串变量。

环顾四周,我认为使用 subprocess.popen 和 subprocess.communicate 提供了最好的解决方案。如下所示的示例代码:

import sys
import tempfile
from subprocess import Popen, PIPE


cmd = [sys.executable, '-c', 'print raw_input()']

# Using a temp file to give input data to the subprocess instead of stdin.write to avoid deadlocks.
with tempfile.TemporaryFile() as f:
    f.write('foobar')
    f.seek(0)  # Return at the start of the file so that the subprocess p1 can read what we wrote.
    p1 = Popen(cmd, stdin=f, stdout=PIPE)

p2 = Popen(cmd, stdin=p1.stdout, stdout=PIPE, stderr=PIPE)
p3 = Popen(cmd, stdin=p2.stdout, stdout=PIPE, stderr=PIPE)

# No order needed.
p1.stdout.close()
p2.stdout.close()

# Using communicate() instead of stdout.read to avoid deadlocks. 
print p3.communicate()[0]

如果我只是将 p2 的标准输出重定向到 p3 的标准输入,上面的代码可以正常工作。

但是,我还想从 p2 收集 stderr 输出并稍后处理它们。不幸的是,我找不到将 p2.stderr 重定向到变量的方法(在这种链式 popen 情况下)。我曾尝试使用 p2.stderr.read() 或只是从 p2.stderr 获取行但都失败了。特别是当p2.stderr的输出很大时,它会挂起p3,整个程序就会陷入死锁。

是否可以将 p2.stderr 存储到某个变量中(因为我需要稍后处理输出)而不挂起程序?

【问题讨论】:

相关:How to thread multiple subprocess instances in Python 2.7? 【参考方案1】:

我遇到了类似的问题,这可能不是理想的解决方案,但您可以将输出重定向到文本文件,然后从那里读取:

tempFile = open("/tmp/myAppName.file.txt","w")
p2 = Popen(cmd, stdin=p1.stdout, stdout=PIPE, stderr=tempFile)
p2out = ""
#when you need the output, just do this:
with open("/tmp/myAppName.file.txt","r") as f:
     p2out = f.read()

【讨论】:

我已经考虑过这个解决方案。我的疑问是,如果 stderr 的输出很大,那么我就失去了管道的目的,因为所有巨大的中间数据都写入了磁盘。但是,再想一想,这实际上没问题,因为我可以编写另一个脚本来解析 stderr 并将其 stdin 链接到中间 stderr。然后我终于可以将我想要的数据重定向到一个临时文件并从那里读出。这非常非常混乱,但它可能会起作用。

以上是关于在Python中,如何将多个进程与popen链接在一起,同时将中间部分结果重定向到一个字符串中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用多处理在Python中运行多个异步进程?

在 Python 中分析子进程 Popen 调用

python popen.communicate() 与多个标准输入写入

可以python子进程Popen接受多个stdin流吗?

如何使用 subprocess.Popen 通过管道连接多个进程?

在 Windows 上的 Python Popen 子进程中暂停 FFmpeg 编码