オブジェクトをカプセル化していても、マルチプロセッシング モジュールは最終的に各プロセスでオブジェクトのローカル コピーを使用することになり、実際に変更をユーザーに伝達することはありません。この場合、Pool.map を適切に使用していません。各メソッド呼び出しが結果を返し、それが戻り値に送り返されることを期待しているためです。共有オブジェクトに影響を与えたい場合は、共有メモリを調整するマネージャーが必要です。
共有オブジェクトのカプセル化
from multiprocessing import Pool
from multiprocessing import Manager
import sys
class encapsulation:
def __init__(self):
self.member_dict = {}
def update_dict(self,index,value):
self.member_dict[index] = value
encaps = encapsulation()
def method(argument):
encaps.update_dict(argument,argument)
# print encaps.member_dict
manager = Manager()
encaps.member_dict = manager.dict()
p = Pool()
p.map(method,sys.argv[1:])
print encaps.member_dict
出力
$ python mp.py a b c
{'a': 'a', 'c': 'c', 'b': 'b'}
共有オブジェクトをメンバー属性として実際に設定するのではなく、引数として渡すか、共有オブジェクト自体をカプセル化してから、その値を dict に渡すことをお勧めします。共有オブジェクトを永続的に保持することはできません。空にして破棄する必要があります。
# copy the values to a reg dict
encaps.member_dict = encaps.member_dict.copy()
しかし、これはさらに良いかもしれません:
class encapsulation:
def __init__(self):
self.member_dict = {}
# normal dict update
def update_dict(self,d):
self.member_dict.update(d)
encaps = encapsulation()
manager = Manager()
results_dict = manager.dict()
# pass in the shared object only
def method(argument):
results_dict[argument] = argument
p = Pool()
p.map(method,sys.argv[1:])
encaps.update_dict(results_dict)
意図したとおりに pool.map を使用する
マップを使用して値を返す場合、次のようになります。
def method(argument):
encaps.update_dict(argument,argument)
return encaps.member_dict
p = Pool()
results = p.map(method,sys.argv[1:])
print results
# [{'a': 'a'}, {'b': 'b'}, {'c': 'c'}]
結果を dict に再度結合する必要があります。
for result in results:
encaps.member_dict.update(result)
print encaps.member_dict
# {'a': 'a', 'c': 'c', 'b': 'b'}