2

I know how to do several "nested" pipes using subprocesses however I have another doubt. I want to do the following:

p1=Popen(cmd1,stdout=PIPE)
p2=Popen(cmd2,stdin=p1.stdout)
p3=Popen(cmd3,stdin=p1.stdout)

Take into account that p3 uses p1.stdout instead of p2.stdout. The problem is that after doing p2, p1.stdout is blank. Please help me!

4

2 回答 2

2

您不能将同一管道发送到两个不同的进程。或者,更确切地说,如果你这样做了,它们最终会访问同一个管道,这意味着如果一个进程读取了某些内容,那么另一个进程将不再可以使用它。

您需要做的是以某种方式“发送”数据。


如果您不需要在数据进入时对其进行流式传输,则可以从 读取所有输出p1,然后将其作为输入发送到p2p3。这很简单:

output = check_output(cmd1)
p2 = Popen(cmd2, stdin=PIPE)
p2.communicate(output)
p3 = Popen(cmd3, stdin=PIPE)
p3.communicate(output)

如果你只需要p2p3并行运行,你可以在一个线程中运行它们。

但是,如果您确实需要实时流媒体,则必须更仔细地进行连接。如果您可以确定p2并且p3将始终使用他们的输入,而不阻塞,比p1提供它的速度更快,您可以在没有线程的情况下执行此操作(只需循环p1.stdout.read()),否则,您将需要每个消费者进程的输出线程,并且一种Queue或其他方式来传递数据。有关如何同步单独线程的更多想法,请参阅源代码。communicate

于 2013-10-15T17:53:07.263 回答
0

如果您想将输出从子进程复制到其他进程而不一次读取所有输出,那么这里是@abarnert 建议的循环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()
于 2013-10-15T19:32:12.443 回答