Pythonで複数プロセスたちあげて結果を非同期で処理する
python で複数プロセス立ち上げてそれぞれのコマンドの結果を非同期に処理するのどうやったらいいんだろ
— ねじめ (@drillbits) October 3, 2013
ていうのを見かけたので殺伐とした心を癒すためにやってみる心。
やりたい事
- Pythonスクリプトから複数外部コマンドを実行
- 実行結果を非同期に処理する
- 割とお手軽にやりたい。
よしググる(クズやろう)
asynchronous - How can I run an external command asynchronously from Python? - Stack Overflow
あった。
試してみる
それぞれ 1秒, 2秒, 3秒まってprintするようなスクリプトを3つ用意
# こんな感じ from time import sleep sleep(1) print "echo1"
これを参考のまんま下記のようなコードで動かす。
from subprocess import Popen, PIPE import time running_procs = [ Popen(['python', 'echo3.py'], stdout=PIPE, stderr=PIPE), Popen(['python', 'echo2.py'], stdout=PIPE, stderr=PIPE), Popen(['python', 'echo1.py'], stdout=PIPE, stderr=PIPE), ] while running_procs: for proc in running_procs: retcode = proc.poll() if retcode is not None: # Process finished. running_procs.remove(proc) break else: # No process is done, wait a bit and check again. time.sleep(.1) continue # Here, `proc` has finished with return code `retcode` if retcode != 0: """Error handling.""" print "error" print proc.stdout.read()
結果はこうなる
$ python hoge.py echo1 echo2 echo3
やってること
1. 3つのプロセスをリストにしてfor inでまわす
2. proc.pollでreturn codeをチェック
3. return codeが帰ってきたら自らをプロセスリストから消してfor終了
4. 逆に3つのプロセスどれもがreturn codeかえさなかったら、ほんのちょっぴりまって1にもどる
5. return codeが帰ってきたらerror handling or stdoutから結果を受け取る
お手軽にやるにはいいかもしんない. proc.poll こういう挙動になるんだてのを知った。
備考
- コマンドが終わるのpollingして、結果が帰ってきた順番に処理してるだけなので正確には非同期で処理してるとは言えない。
- 例えば最後のstdoutからreadしたものをあれやらこれや処理するとしたら、その間ブロックされるので、その後の結果は処理されるのが待たされる。
はー癒された