2

「標準」のサブプロセス パイプライン手法 (例: http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline ) を 2 つのパイプラインに「アップグレード」できますか?

# How about
p1 = Popen(["cmd1"], stdout=PIPE, stderr=PIPE)
p2 = Popen(["cmd2"], stdin=p1.stdout)
p3 = Popen(["cmd3"], stdin=p1.stderr)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p1.stderr.close()
#p2.communicate()  # or p3.communicate()?

OK、実際には別の使用例ですが、最も近い出発点はパイプラインの例のようです。ところで、「通常の」パイプラインの p2.communicate() はどのように p1 を駆動するのでしょうか? 参照用の通常のパイプラインは次のとおりです。

# From Python docs
output=`dmesg | grep hda`
# becomes
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

communicate()最終的には、どのような種類の「プロセス グラフ」(または単なるツリーか?) がサポートできることに興味があると思いますが、一般的なケースについては別の日に譲ります。

更新: ベースライン機能は次のとおりです。communicate() なしで、p1.stdout と p2.stdout から読み取る 2 つのスレッドを作成します。メイン プロセスでは、p1.stdin.write() を介して入力を挿入します。問題は、単に communicate() を使用して 1 ソース、2 シンク グラフを駆動できるかどうかです。

4

2 に答える 2

2

bash のプロセス置換を使用できます。

from subprocess import check_call

check_call("cmd1 > >(cmd2) 2> >(cmd3)", shell=True, executable="/bin/bash")

cmd1の stdout をにリダイレクトしcmd2cmd1の stderr をにリダイレクトしcmd3ます。

使用したくない場合はbash、質問のコードがそのまま機能するはずです。

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE
from textwrap import dedent

# generate some output on stdout/stderr
source = Popen([sys.executable, "-c", dedent("""
    from __future__ import print_function
    import sys
    from itertools import cycle
    from string import ascii_lowercase

    for i, c in enumerate(cycle(ascii_lowercase)):
        print(c)
        print(i, file=sys.stderr)
""")], stdout=PIPE, stderr=PIPE)

# convert input to upper case
sink = Popen([sys.executable, "-c", dedent("""
    import sys

    for line in sys.stdin:
        sys.stdout.write(line.upper())
""")], stdin=source.stdout)
source.stdout.close() # allow source to receive SIGPIPE if sink exits

# square input
sink_stderr = Popen([sys.executable, "-c", dedent("""
   import sys

   for line in sys.stdin:
       print(int(line)**2)
""")], stdin=source.stderr)
source.stderr.close() # allow source to receive SIGPIPE if sink_stderr exits

sink.communicate()
sink_stderr.communicate()
source.wait()
于 2013-10-28T09:31:25.033 に答える
0

ここでの解決策は、1 つのプロセスからの出力を読み取り、それを複数のプロセスの入力に書き込むバックグラウンド スレッドをいくつか作成することです。

targets = [...] # list of processes as returned by Popen()
while True:
    line = p1.readline()
    if line is None: break
    for p in targets:
        p.stdin.write(line)
于 2013-10-28T10:46:42.773 に答える