conta's diary

思ったこと、やったことを書いてます。 twitter: @conta_

Pythonのmultiprocessing.PoolでExceptionを受け取る

Pythonで並列にいろいろ処理させたいなと思い、multiprocessing.Poolをつかってプログラムを作っていたらぶち当たった問題。

下記のコードを動かしていた、実はバグあり。

出力は

start main
end main

??おかしい。本当ならworkerのprint関数が実行される、はず。

実は

res = pool.apply_async(worker, (i))

じゃなくて

res = pool.apply_async(worker, (i,))

じゃないといけない。引数をタプルとして認識してくれないのが原因だ。

修正してみる。

出力は

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
worker i: 7
end worker
end worker
end worker
end worker
end worker
end worker
end worker
end worker
end main

おー、治った。 しかしながら、エラーがわからん!!

困った、Exception出して欲しいよ(´・ω・`)

ちょっとWorkerでException投げてテストしてみる。 i == 6の時に例外を投げる。

出力

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
worker i: 7
end worker: 1
end worker: 2
end worker: 3
end worker: 0
end worker: 4
end worker: 5
end worker: 7
end main

うん、正常に動いて、ないね。6番が抜けてるけど、Exceptionはスルー。 困った。 教えて、すたっくおーばーふろー先生。

python - Exception thrown in multiprocessing Pool not detected - Stack Overflow

16.6. multiprocessing — Process-based “threading” interface — Python v2.7.6 documentation

なるほど、AsyncResult.get()という関数を使うと例外が投げられるのね

get()を呼んでみる。

start main
worker i: 0
worker i: 1
worker i: 2
worker i: 3
worker i: 4
worker i: 5
worker i: 6
end worker: 1
end worker: 0
worker i: 7
end worker: 2
end worker: 5
end worker: 3
end worker: 4
end worker: 7
end main
Traceback (most recent call last):
  File "pool_test_4.py", line 30, in <module>
    main()
  File "pool_test_4.py", line 26, in main
    res.get()
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 554, in get
    raise self._value
Exception: help me! 6

おー、でたでた! res.get()、覚えておこう。 これで快適multiprocessing生活(・∀・)