我知道如何使用子进程执行多个“嵌套”管道但是我有另一个疑问。我想做以下事情:
p1=Popen(cmd1,stdout=PIPE)
p2=Popen(cmd2,stdin=p1.stdout)
p3=Popen(cmd3,stdin=p1.stdout)
考虑到p3使用p1.stdout而不是p2.stdout。问题是在执行p2之后,p1.stdout为空。请帮帮我!
答案 0 :(得分:2)
您无法将同一管道发送到两个不同的进程。或者,相反,如果你这样做,他们最终会访问同一个管道,这意味着如果一个进程读取某个进程,则它不再可用于另一个进程。
您需要做的是以某种方式“发送”数据。
如果您不需要流式传输数据,则可以阅读p1
的所有输出,然后将其作为输入发送给p2
和p3
。这很简单:
output = check_output(cmd1)
p2 = Popen(cmd2, stdin=PIPE)
p2.communicate(output)
p3 = Popen(cmd3, stdin=PIPE)
p3.communicate(output)
如果你只需要p2
和p3
并行运行,你可以在一个线程中运行它们。
但如果您确实需要实时流式传输,则必须更仔细地进行连接。如果你可以确定p2
和p3
将始终消耗他们的输入,而不是阻塞,比p1
提供的速度更快,你可以在没有线程的情况下执行此操作(只需循环{{1除此之外,你需要为每个消费者进程提供一个输出线程,以及p1.stdout.read()
或其他一些传递数据的方法。有关如何同步单独线程的更多提示,请参阅source code至Queue
。
答案 1 :(得分:0)
如果要将子流程的输出复制到其他流程而不一次读取所有输出,那么@abarnert's suggestion的实现将循环p1.stdout
以实现它:
from subprocess import Popen, PIPE
# start subprocesses
p1 = Popen(cmd1, stdout=PIPE, bufsize=1)
p2 = Popen(cmd2, stdin=PIPE, bufsize=1)
p3 = Popen(cmd3, stdin=PIPE, bufsize=1)
# "tee" the data
for line in iter(p1.stdout.readline, b''): # assume line-oriented data
p2.stdin.write(line)
p3.stdin.write(line)
# clean up
for pipe in [p1.stdout, p2.stdin, p3.stdin]:
pipe.close()
for proc in [p1, p2, p3]:
proc.wait()