只是试验和学习,我知道如何创建一个可以通过多个程序访问的共享字典,但我不知道如何保持dict同步。我相信,defaultdict
说明了我遇到的问题。
from collections import defaultdict
from multiprocessing import Pool, Manager, Process
#test without multiprocessing
s = 'mississippi'
d = defaultdict(int)
for k in s:
d[k] += 1
print d.items() # Success! result: [('i', 4), ('p', 2), ('s', 4), ('m', 1)]
print '*'*10, ' with multiprocessing ', '*'*10
def test(k, multi_dict):
multi_dict[k] += 1
if __name__ == '__main__':
pool = Pool(processes=4)
mgr = Manager()
multi_d = mgr.dict()
for k in s:
pool.apply_async(test, (k, multi_d))
# Mark pool as closed -- no more tasks can be added.
pool.close()
# Wait for tasks to exit
pool.join()
# Output results
print multi_d.items() #FAIL
print '*'*10, ' with multiprocessing and process module like on python site example', '*'*10
def test2(k, multi_dict2):
multi_dict2[k] += 1
if __name__ == '__main__':
manager = Manager()
multi_d2 = manager.dict()
for k in s:
p = Process(target=test2, args=(k, multi_d2))
p.start()
p.join()
print multi_d2 #FAIL
第一个结果有效(因为它没有使用multiprocessing
),但是我在使用multiprocessing
时遇到了问题。我不确定如何解决它,但我认为可能是因为它没有被同步(并且稍后加入结果)或者因为在multiprocessing
内我无法想出如何将defaultdict(int)
设置为字典。
任何有关如何使其发挥作用的帮助或建议都会很棒!
答案 0 :(得分:11)
您可以继承BaseManager
并注册其他类型以进行共享。在默认AutoProxy
生成的类型不起作用的情况下,您需要提供合适的代理类型。对于defaultdict
,如果您只需要访问dict
中已存在的属性,则可以使用DictProxy
。
from multiprocessing import Pool
from multiprocessing.managers import BaseManager, DictProxy
from collections import defaultdict
class MyManager(BaseManager):
pass
MyManager.register('defaultdict', defaultdict, DictProxy)
def test(k, multi_dict):
multi_dict[k] += 1
if __name__ == '__main__':
pool = Pool(processes=4)
mgr = MyManager()
mgr.start()
multi_d = mgr.defaultdict(int)
for k in 'mississippi':
pool.apply_async(test, (k, multi_d))
pool.close()
pool.join()
print multi_d.items()
答案 1 :(得分:3)
嗯,Manager
类似乎只提供固定数量的预定义数据结构,这些数据结构可以在进程间共享,defaultdict
不在其中。如果你真的需要那个defaultdict
,最简单的解决方案就是自己实现默认行为:
def test(k, multi_dict):
if k not in multi_dict:
multi_dict[k] = 0
multi_dict[k] += 1