我想创建一个可以跨进程共享的OrderedDict
实例。
我已经实现了正常的dict
版本,即多进程dict
版本,如下所示。
import multiprocessing as mp
class BasicPen(object):
"""single process version"""
def __init__(self, words):
self.dogs = {"Molson": [], "Taco": [], "Lucky": []}
self.punc = "!"
for dog_name in self.dogs.keys():
self.bark(dog_name, words)
def bark(self, dog, words):
for word in words:
self.dogs[dog].append(word + self.punc)
class MultiPen(object):
"""multiprocess dict"""
def __init__(self, words):
self.man = mp.Manager()
self.dogs = self.man.dict()
self.dogs["Molson"] = self.man.list()
self.dogs["Taco"] = self.man.list()
self.dogs["Lucky"] = self.man.list()
self.punc = "!"
procs = [mp.Process(target=self.bark, args=(dog_name, words)) for dog_name in self.dogs.keys()]
for pr in procs:
pr.start()
for pr in procs:
pr.join()
def bark(self, dog, words):
for word in words:
self.dogs[dog] += [word + self.punc]
if __name__ == '__main__':
print("multi")
m_pen = MultiPen(["bark", "woof", "yip"])
print(m_pen.dogs)
print("basic")
b_pen = BasicPen(["bark", "woof", "yip"])
print(b_pen.dogs)
multiprocessing.Namespace
我尝试使用OrderedDict
使用multiprocessing.Namespace()
版本来实现版本,如下所示:
import multiprocessing as mp
from collections import OrderedDict
class NamePen(object):
"""ordered dict attempt"""
def __init__(self, words):
man = mp.Manager()
self.ns = man.Namespace()
self.ns.dogs = OrderedDict()
self.ns.dogs["Lucky"] = man.list()
self.ns.dogs["Molson"] = man.list()
self.ns.dogs["Taco"] = man.list()
self.punc = "!"
procs = [mp.Process(target=self.bark, args=(dog_name, words)) for dog_name in self.ns.dogs.keys()]
for pr in procs:
pr.start()
for pr in procs:
pr.join()
def bark(self, dog, words):
for word in words:
self.ns.dogs[dog] += [word + self.punc]
if __name__ == '__main__':
print("ordered")
n_pen = NamePen(["bark", "woof", "yip"])
print(n_pen.ns.dogs)
当我运行此代码时,NamePen
会返回一个空的OrderedDict
。我考虑的另一个选择是创建multiprocessing.Namespace
并仅将属性指定为字典键,但是我找不到列出属性的方法,因为在__dict__
上运行multiprocessing.Namespace
并没有工作。因此,我开始怀疑multiprocessing.Namespace
方法是否正确。
multiprocessing.managers.BaseManager
阅读完GMFBridge后,我尝试使用BaseManager
推荐的方法:
import multiprocessing as mp
from multiprocessing.managers import BaseManager
from collections import OrderedDict
class MultiPen(object):
def __init__(self, words):
man = BaseManager()
man.register('OrderedDict', OrderedDict)
man.start()
self.dogs = man.OrderedDict()
self.dogs.update(molson=[])
self.dogs.update(taco=[])
self.dogs.update(lucky=[])
self.punc = "!"
procs = [mp.Process(target=self.bark, args=(dog_name, words)) for dog_name in self.dogs.keys()]
for pr in procs:
pr.start()
for pr in procs:
pr.join()
def bark(self, dog, words):
for word in words:
self.dogs[dog] += [word + self.punc]
if __name__ == '__main__':
print("multi")
m_pen = MultiPen(["bark", "woof", "yip"])
print(m_pen.dogs)
但是,我收到以下错误:
Traceback (most recent call last):
File "multiproc_class.py", line 43, in <module>
m_pen = MultiPen(["bark", "woof", "yip"])
File "multiproc_class.py", line 17, in __init__
procs = [mp.Process(target=self.bark, args=(dog_name, words)) for dog_name in self.dogs.keys()]
File "<string>", line 2, in keys
File "/usr/lib/python3.5/multiprocessing/managers.py", line 732, in _callmethod
raise convert_to_error(kind, result)
multiprocessing.managers.RemoteError:
---------------------------------------------------------------------------
Unserializable message: ('#RETURN', odict_keys(['molson', 'taco', 'lucky']))
---------------------------------------------------------------------------
我认为这意味着我正在错误地使用对象管理器。
我不在乎是否需要使用库或自定义类。但是,OrderedDict必须是类的属性,如上例所示。