Python で並列処理をするときに、multiprocessing の pool.Pool() でエラーが出ました。
その解決方法です。
『Windows 7』で実行していたときは問題なく動いていたのですが、『Linux Mint』で実行したときに、『Exception escaped from start_client』とか、『RuntimeError: already started』といったエラーが出ました。
そして最後に、『Terminated』と表示されて、プログラムが止まりました。
エラーは『デバッグモード』で動かしたときにだけ、発生しました。
結論ですが、同じく multiprocessing の中にある set_start_method() を使ったところ、エラーが出なくなりました。
そのときのコード例を紹介します。
問題のコード ⇒ pool.Pool() でエラー
multiprocessing の pool.Pool() で、エラーが出た時のコードです。
エラーですが、with 文のところで発生していました。
with 文の as 節で受け取った p で何かをする前に、エラーが発生していました。
from multiprocessing import pool
def main():
with pool.Pool(processes=1) as p: # ← ここでエラー発生
print('ok')
return
if __name__ == "__main__":
main()
エラーが出たときの実行環境は、Linux Mint 19.2、Python 3.6.8 です。
Virtual Box 6.0 の中で実行しました。
Visual Studio Code を使って、デバッグモードで実行したときにだけ、エラーが出ました。たとえば、『デバッグの開始』や『F5キー』で実行したときに、エラーが出ました。
一方で、『デバッグなしで開始』や『ターミナルで Python ファイルを実行』で実行したときは、エラー無く実行できました。
Windows 7 で実行したときは、デバッグモードでも、そうでなくても、エラーは出ませんでした。
実行結果 (Exception escaped from start_client)
エラーが出た時の実行結果です。
E00000.257: Exception escaped from start_client
Traceback (most recent call last):
File "/home/*/extensions/ms-python.python-2019.9.34911/pythonFiles/lib/python/ptvsd/log.py", line 110, in g
return f(*args, **kwargs)
File "/home/*/extensions/ms-python.python-2019.9.34911/pythonFiles/lib/python/ptvsd/pydevd_hooks.py", line 74, in start_client
sock, start_session = daemon.start_client((host, port))
File "/home/*/extensions/ms-python.python-2019.9.34911/pythonFiles/lib/python/ptvsd/daemon.py", line 214, in start_client
with self.started():
File "/usr/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "/home/*/extensions/ms-python.python-2019.9.34911/pythonFiles/lib/python/ptvsd/daemon.py", line 110, in started
self.start()
File "/home/*/extensions/ms-python.python-2019.9.34911/pythonFiles/lib/python/ptvsd/daemon.py", line 145, in start
raise RuntimeError('already started')
RuntimeError: already started
Traceback (most recent call last):
Terminated
Exception escaped from start_client や、RuntimeError: already started といった内容のエラーが表示されています。
※『E00000.257:』のところの数字は、実行するたびに変わりました。
解決したコード ⇒ set_start_method() を追加
解決方法ですが、マルチプロセッシング (multiprocessing) のパッケージから、セットスタートメソッド (set_start_method) をインポートして使いました。
自分の場合は、これで解決しました。
デバッグモードでプログラムを実行しても、エラーが出なくなりました。
解決したときのコードです。
from multiprocessing import pool
from multiprocessing import set_start_method
def main():
with pool.Pool(processes=1) as p:
print('ok')
return
if __name__ == "__main__":
# set_start_method() は、ここに書いてくださいとのこと。
set_start_method('spawn', True)
main()
Python マニュアルの場所です。
multiprocessing プロセスベースの並列処理
- class multiprocessing.pool.Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])
- multiprocessing.set_start_method(method)
- コンテキストと開始方式(method に使う fork, spawn, forkserver の説明)
ところで、set_start_method() を書く場所ですが、上記の公式マニュアルに指示がありました。
if __name__ == "__main__":
の節内に書きましょうとのことでした。
multiprocessing.set_start_method(method)
子プロセスの開始方式を指定します。method には'fork'
、'spawn'
あるいは'forkserver'
を指定できます。これは一度しか呼び出すことができず、その場所もメインモジュールの
if __name__ == '__main__'
節内で保護された状態でなければなりません。バージョン 3.4 で追加.
multiprocessing — プロセスベースの並列処理 — Python 3.7.4 ドキュメント
実行結果 OK
解決したコードで、プログラムを実行した結果です。
Linux Mint ⇒ Visual Studio Code ⇒『デバッグ開始』で実行しました。
ok
print() で表示した ok だけが出ました。
set_start_method() を使ったことで、デバッグモードで実行しても、エラーが出なくなりました。
以上です。
並列処理のコード例は、以下の記事にも書きました。