2

subprocessパイプラインにつなぎ合わせたいインスタンスがいくつかありますが、行き詰まっており、アドバイスを求めたいと考えています。

たとえば、次のように模倣します。

cat data | foo - | bar - > result

または:

foo - < data | bar - > result

...私は最初に次のことを試しましたが、ハングします:

import subprocess, sys

firstProcess = subprocess.Popen(['foo', '-'], stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE)
secondProcess = subprocess.Popen(['bar', '-'], stdin=firstProcess.stdout,
                                 stdout=sys.stdout)

for line in sys.stdin:
    firstProcess.stdin.write(line)
    firstProcess.stdin.flush()

firstProcess.stdin.close()
firstProcess.wait()

2 回目の試行では、パラメーターを使用して 1 つのsubprocessインスタンスを使用します。これは機能します。shell=True

import subprocess, sys

pipedProcess = subprocess.Popen(" ".join(['foo', '-', '|', 'bar', '-']),
                                stdin=subprocess.PIPE, shell=True)

for line in sys.stdin:
    pipedProcess.stdin.write(line)
    pipedProcess.stdin.flush()

pipedProcess.stdin.close()
pipedProcess.wait()

subprocess最初の連鎖アプローチで何が間違っていますか? 使用しないのが最善であると読みましたshell=Trueが、最初のアプローチで何が間違っているのか知りたいです。アドバイスありがとうございます。

編集

質問のタイプミスを修正し、 のstdinパラメータを修正しましたsecondProcess。まだハングしています。

firstProcess.wait()ハングを解決する削除も試みましたが、0バイトのファイルがresult.

pipedProcessうまく機能するので、私は に固執します。しかし、最初のセットアップがハングしたり、出力として 0 バイトのファイルを作成したりする理由を誰かが知っている場合は、その理由も知りたいと思います。

4

2 に答える 2

2

shell=Trueコマンドライン全体を解釈し、パイプ自体を処理するようにシェルに要求しているため、機能します。foo - | bar -これは、シェルに直接入力した場合と実質的に同じです。

(これが、 を使用するのが安全でない理由でもありますshell=True。コマンドと引数を、解析の対象とならないリストとして直接渡すと、シェルをだまして悪いことをさせる方法がたくさんあります。仲介者。)

于 2013-03-12T23:50:06.537 に答える
1

最初の例を修正するには、ドキュメントの提案foo_process.stdout.close()に従って追加します。次のコードはコマンドをエミュレートします。foo - | bar -

#!/usr/bin/python
from subprocess import Popen, PIPE

foo_process = Popen(['foo', '-'], stdout=PIPE)
bar_process = Popen(['bar', '-'], stdin=foo_process.stdout)
foo_process.stdout.close() # allow foo to know if bar ends
bar_process.communicate()  # equivalent to bar_process.wait() in this case  

、と異なる場合を除いて、ここsys.stdinで明示的にを使用する必要はありません。sys.stdoutsys.__stdin__sys.__stdout__

コマンドをエミュレートするにはfoo - < data | bar - > result

#!/usr/bin/python
from subprocess import Popen, PIPE

with open('data','rb') as input_file, open('result', 'wb') as output_file:
    foo = Popen(['foo', '-'], stdin=input_file, stdout=PIPE)
    bar = Popen(['bar', '-'], stdin=foo.stdout, stdout=output_file)
    foo.stdout.close() # allow foo to know if bar ends
bar.wait()

変更された入力を行ごとにプロセスにフィードする場合、つまりコマンドfooをエミュレートする場合:python modify_input.py | foo - | bar -

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

foo_process = Popen(['foo', '-'], stdin=PIPE, stdout=PIPE)
bar_process = Popen(['bar', '-'], stdin=foo_process.stdout)
foo_process.stdout.close() # allow foo to know if bar ends
for line in sys.stdin:
    print >>foo_process.stdin, "PY", line, # modify input, feed it to `foo`
foo_process.stdin.close() # tell foo there is no more input
bar_process.wait()
于 2013-03-13T00:17:26.397 に答える