我有一个具有两个属性的对象:一个dict和一个int。当我通过multiprocessing.Pool使用分叉进程修改对象时,我用它修改了int属性,但是没有修改dict。那是为什么?
from multiprocessing import Pool
def fork():
someObject = SomeClass()
for i in range(10):
someObject.method(i)
print("in fork, someObject has dct=%s and nbr=%i" % (someObject.dct, someObject.nbr))
return someObject
def test():
pool = Pool(processes=1)
result = pool.apply(func=fork)
print("in main, someObject has dct=%s and nbr=%i" % (result.dct, result.nbr))
class SomeClass(object):
dct = {}
nbr = 0
def method(self, nbr):
self.dct[nbr]=nbr
self.nbr+=nbr
if __name__=='__main__':
test()
输出:
在fork中,someObject有dct = {0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9 }和nbr = 45
在main中,someObject有dct = {}和nbr = 45
答案 0 :(得分:2)
父进程与子进程的副本SomeClass.dct
和SomeClass.nbt
不同。
nbr
更新但不是dct
的原因是nbr
实际上变成了一个实例变量self.nbr+=nbr
,它被腌制并发送回父进程。但是,您永远不会将self.dct
分配给任何内容,因此self.dct
(实际上指的是SomeClass.dct
)不会被腌制。
您可以通过在__getstate__()
上定义SomeClass
来了解这一点:
class SomeClass(object):
dct = {}
nbr = 0
def method(self, nbr):
self.dct[nbr]=nbr
self.nbr+=nbr
def __getstate__(self):
res = self.__dict__
print("pickled", res)
return res
打印:
in fork, someObject has dct={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} and nbr=45
('pickled', {'nbr': 45})
in main, someObject has dct={} and nbr=45
您可以通过将dct
分配给"本身"来强制class SomeClass(object):
dct = {}
nbr = 0
def method(self, nbr):
self.dct[nbr]=nbr
self.dct = self.dct
self.nbr+=nbr
进行腌制:
in fork, someObject has dct={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} and nbr=45
('pickled', {'nbr': 45, 'dct': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}})
in main, someObject has dct={0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} and nbr=45
打印:
{{1}}
答案 1 :(得分:1)
我找到了另一种解决方案。我没有使用dict()
,而是使用了multiprocessing.Manager.dict()
,它按预期工作。