代码之家  ›  专栏  ›  技术社区  ›  Derek Farren

通过Python多处理修改对象。池:奇怪的行为

  •  0
  • Derek Farren  · 技术社区  · 10 年前

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

    大体上,someObject的dct={},nbr=45

    2 回复  |  直到 10 年前
        1
  •  2
  •   univerio    10 年前

    父进程具有的不同副本 SomeClass.dct SomeClass.nbt 而不是子进程。

    原因 nbr 已更新但未更新 dct 是吗 全国广播电台 当您这样做时,实际上变成了一个实例变量 self.nbr+=nbr ,它将被腌制并发送回父进程。但你从不分配 self.dct 任何事情,所以 自我诊断 (实际上是指 某些类别.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
    

    你可以强迫 离散余弦变换 通过将其分配给“自身”进行腌制:

    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
    
        2
  •  1
  •   Derek Farren    10 年前

    我找到了另一种解决方案。而不是使用 dict() ,我使用了 multiprocessing.Manager.dict() 并且它如预期的那样工作。