2

一連のファイルに対して並行して実行したい一連のコマンド ライン ツールがあります。次のようなものをラップするためのpython関数を作成しました。

def process_file(fn):
    print os.getpid()
    cmd1 = "echo "+fn
    p = subprocess.Popen(shlex.split(cmd1))

    # after cmd1 finishes
    other_python_function_to_do_something_to_file(fn)

    cmd2 = "echo "+fn
    p = subprocess.Popen(shlex.split(cmd2))
    print "finish"

if __name__=="__main__":
    import multiprocessing
    p = multiprocessing.Pool()
    for fn in files:
        RETURN = p.apply_async(process_file,args=(fn,),kwds={some_kwds})

これは機能しますが、複数のプロセスを実行しているようには見えません。シリアルで実行されているようです(Pool(5)同じ結果で使用してみました)。私は何が欠けていますか?Popen「ブロッキング」への呼び出しですか?

編集:少し明確にしました。各ファイルで順番に実行するには、cmd1、次にいくつかのpythonコマンド、次にcmd2が必要です。

EDIT2: 上記の出力には次のパターンがあります。

pid
finish
pid
finish
pid
finish

同様の呼び出しでmap、代わりにapply(ただし、 を渡すための規定なしで) を使用すると、kwds次のように見えます。

pid
pid
pid
finish
finish
finish

ただし、マップ呼び出しは、明らかに成功した後に時々 (常に?) ハングします。

4

1 に答える 1

3

Popen「ブロッキング」への呼び出しですか?

いいえ。subprocess.Popen返品をすぐに作成するだけで、待機または使用できるオブジェクトが得られます。ブロックしたい場合、それは簡単です:

subprocess.check_call(shlex.split(cmd1))

その間、引数を文字列にまとめてshlexからリストに戻そうとする理由がわかりません。リストを書くだけではどうですか?

cmd1 = ["echo", fn]
subprocess.check_call(cmd1)

これは機能しますが、複数のプロセスを実行しているようには見えません。シリアルで実行されているようです

どうしてそう思うのですか?各プロセスがバックグラウンドで 2 つのプロセスを開始するだけなので、それらが並行して実行されているかどうかを判断するのは非常に困難です。

複数の処理から作業を取得していることを確認したい場合は、いくつかの出力またはログを追加したい場合があります (そしてos.getpid()、メッセージに何かをスローします)。

multiprocessing.Pool.map_async一方、ループの out の効果を正確に複製しようとしているように見えますmultiprocessing.Pool.apply_asyncが、結果を累積する代わりに、呼び出された変数にそれぞれを隠してRESULTから、使用する前に捨てています。なぜ使用しないのmap_asyncですか?

最後に、あなたはmultiprocessing仕事に適したツールかどうかを尋ねました。まあ、明らかに非同期の何かが必要です:check_call(args(file1))をブロックする必要がありますother_python_function_to_do_something_to_file(file1)が、同時にブロックしない必要がありますcheck_call(args(file2))

私はおそらく を使用threadingしていたでしょうが、実際には大きな違いはありません。プロセスの起動にコストがかかるプラットフォームを使用している場合でも、ポイント全体で N * M 束の子プロセスが実行されているため、すでにそのコストを支払っています。したがって、別の 8 つのプールを使用しても問題はありません。また、スレッド間でデータを共有して誤って競合を作成したり、共有するものが何もないため、プロセス間でデータを共有していないように見えるコードを誤って作成したりするリスクはほとんどありません。だから、どちらが好きでも、それを選んでください。

もう 1 つの方法は、イベント ループを記述することです。この問題のために実際に自分でやり始めるかもしれませんが、後悔するので、あなたはやるべきではありません…</p>

于 2012-11-07T23:15:14.163 に答える