通过Python multiprocessing.Pool修改对象:奇怪的行为

时间:2014-08-01 00:26:16

标签: python multiprocessing pickle pool

我有一个具有两个属性的对象:一个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

2 个答案:

答案 0 :(得分:2)

父进程与子进程的副本SomeClass.dctSomeClass.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(),它按预期工作。