【问题标题】:Updating member variable of object while using multprocessing pool使用多处理池时更新对象的成员变量
【发布时间】:2020-02-19 00:54:56
【问题描述】:

我有一个班级B,它由另一个班级A组成。

在B 类中,我正在使用多处理池从A 类中调用一个方法。此方法更新A 的成员变量(这是一个字典)。

当我打印出这个成员变量时,它似乎没有被更新。这是描述问题的代码:

import multiprocessing as mp

class A():
    def __init__(self):
        self.aDict = {'key': 0}

    def set_lock(self, lock):
        self.lock = lock

    def do_work(self, item):
        print("Doing work for item: {}".format(item) )
        self.aDict['key'] += 1

        return [1,2,3] # return some list

class B():
    def __init__(self):
        self.objA = A()

    def run_with_mp(self):
        items=['item1', 'item2']
        with mp.Pool(processes=mp.cpu_count()) as pool:
            result = pool.map_async(self.objA.do_work, items)
            result.wait()
            pool.terminate()

        print(self.objA.aDict)

    def run(self):
        items=['item1', 'item2']
        for item in items:
            self.objA.do_work(item)

        print(self.objA.aDict)

if __name__ == "__main__":
    b = B()
    b.run_with_mp() # prints {'key': 0}
    b.run()         # prints {'key': 2}

b.run_with_mp() 打印 {'key': 0} 整个 b.run() 打印 {'key': 2}。我认为多处理池版本也会这样做,因为对象self.objA 具有运行多处理池的B 的完整类的范围。

我认为池中的每个工作人员看到的 self.objA 版本不同,这与主程序流程中的不同。有没有办法让所有工作人员更新一个公共变量?

【问题讨论】:

    标签: python python-3.x python-multiprocessing


    【解决方案1】:

    你已经接近解释了,确实,每个衍生的进程都有自己的内存区域,这意味着它们是独立的。当您运行do_work 时,每个进程都会更新其aDict 的版本,因为该变量不是共享的。如果要共享变量,最简单的方法是使用Manager,例如:

    import multiprocessing as mp
    
    class A():
        def __init__(self):
            self.aDict = mp.Manager().dict({'key': 0})
    
        def set_lock(self, lock):
            self.lock = lock
    
        def do_work(self, item):
            print("Doing work for item: {}".format(item) )
            self.aDict['key'] += 1
    
            return [1,2,3] # return some list
    
    class B():
        def __init__(self):
            self.objA = A()
    
        def run_with_mp(self):
            items=['item1', 'item2']
            with mp.Pool(processes=mp.cpu_count()) as pool:
                result = pool.map_async(self.objA.do_work, items)
                result.wait()
                pool.terminate()
    
            print(self.objA.aDict)
    
        def run(self):
            items=['item1', 'item2']
            for item in items:
                self.objA.do_work(item)
    
            print(self.objA.aDict)
    
    if __name__ == "__main__":
        b = B()
        b.run_with_mp() # prints {'key': 2}
        b.run()         # prints {'key': 4}
    

    我修改了您的示例以共享 aDict 变量,因此每个进程都会更新该属性(run_with_mp 和 run 方法)。考虑在docs阅读更多内容。

    【讨论】:

    • 谢谢,如果我使用简单的字典,当我使用 mp.Manager() 中的 dict() 时,它可以工作。当我有其他对象作为 dict 内的键的值时,例如self.aDict = mp.Manager().dict({'key': set()}) 和do_work(),我做self.aDictt['key'].add(item) 它似乎不起作用。 set() 始终为空。这是应该的样子吗?
    • @Bharat 是的,这是一个已知问题,这是一个关于它的 SO 问题stackoverflow.com/questions/37510076/…。基本上,尝试分享简单的对象。
    • 谢谢,我使用了在回答该问题时描述的方式,从 dict 中获取值,添加项目,然后将其分配回密钥。这行得通。
    猜你喜欢
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2021-07-22
    • 2016-07-30
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多