使用多进程池时更新对象的成员变量

2024-06-17 13:12:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类B,它由另一个类A组成

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

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

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,这与主程序流中的版本不同。有没有办法让所有工作人员更新一个公共变量


Tags: keyrunselflockdefwithitemsmp
1条回答
网友
1楼 · 发布于 2024-06-17 13:12:37

您已经接近解释了,事实上,每个派生的进程都拥有自己的内存区域,这意味着它们是独立的。运行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_mprun方法)。考虑在docs中读取更多信息。

相关问题 更多 >