1.はじめに
PythonでMultiprocessingを使った並列処理を実装しているときに、配列型のデータをプロセス間で共有する処理に詰まったので備忘録として残しておきます。 実装した時のpythonのバージョンは3.7.1です。2.実装内容
実装内容は下記の2つの関数を並列処理にして引数にとるリストをプロセス間で共有する処理です。 ①3秒ごとに引数として受け取ったリストを表示する処理 ②2秒ごとに引数として受け取ったリストにaを追加する処理プロセス間の状態管理にはManagerオブジェクトを使用しました。
3.間違った実装
```python from multiprocessing import Process, Manager import time3秒ごとにリストを表示する
def list_print(test_list):
while True:
print(str(test_list))
time.sleep(3)
2秒ごとにリストにaを追加する
def list_append(test_list):
while True:
test_list.append("a")
time.sleep(2)
if name == 'main':
manager = Manager()
test_list=manager.list()
print("関数実行前のリスト" +str(test_list))
p1=Process(target=list_print,args=(test_list))
p2=Process(target=list_append,args=(test_list))
p1.start()
p2.start()
p1.join()
p2.join()
<h2>4.実行結果</h2>
Traceback (most recent call last):
Traceback (most recent call last):
File "/Applications/anaconda3/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
self.run()
File "/Applications/anaconda3/lib/python3.7/multiprocessing/process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "/Applications/anaconda3/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
self.run()
File "/Applications/anaconda3/lib/python3.7/multiprocessing/process.py", line 99, in run
self._target(*self._args, **self._kwargs)
TypeError: list_append() missing 1 required positional argument: 'test_list'
TypeError: list_print() missing 1 required positional argument: 'test_list'
どうやら引数の取り方が悪く、エラーが出てしまったようです。
もしかしてManagerオブジェクトはリスト型には対応していないのではないかと思いましたが、公式にはがっつりとリストに対応しています、と書いてありました。
そこでしばらくリファレンスを読んでいたら解決策を見つけました。
<h2>5.解決方法</h2>
実行する関数の一つ目の引数に辞書を定義してあげることで解決できました。
空の辞書dummyを定義して引数に取ってます。
コードは下記になります。
```python
from multiprocessing import Process,Manager
import time
# リストを表示する
def list_print(dummy, test_list):
while True:
print(str(test_list))
time.sleep(3)
# リストにaを追加する
def list_append(dummy, test_list):
while True:
test_list.append("a")
time.sleep(2)
if __name__ == '__main__':
manager = Manager()
#空の辞書を定義
dummy = manager.dict()
test_list=manager.list()
print("関数実行前のリスト" +str(test_list))
#1つ目の引数に空の辞書を追加
p1=Process(target=list_print,args=(dummy, test_list))
p2=Process(target=list_append,args=(dummy, test_list))
p1.start()
p2.start()
p1.join()
p2.join()
6.実行結果
実行結果は下記になります。 無事に配列の表示と追加が確認できました。関数実行前のリスト[]
[]
['a', 'a']
['a', 'a', 'a']
['a', 'a', 'a', 'a', 'a']
以上です。