You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用multiprocessing并行处理对象实例时属性未更新问题排查

Python多进程更新对象属性失效问题分析与解决

问题重现

串行执行时,对象的bar属性能被正确设置为1.0:

class Foo:
    
    def __init__(self):
        self.bar = None
        
    def put_bar(self):
        self.bar = 1.0


if __name__ == "__main__":
    
    instances = [Foo() for _ in range(100)]
    
    for instance in instances:
        instance.put_bar()
       
    # 输出1.0
    print(instances[0].bar)

但改用multiprocessing.Pool并行处理后,原对象的bar属性仍为None:

import os
from multiprocessing import Pool


class Foo:

    def __init__(self):
        self.bar = None

    def put_bar(self):
        self.bar = 1.0


def worker(instance):
    return instance.put_bar()


if __name__ == "__main__":

    instances = [Foo() for _ in range(100)]

    with Pool(os.cpu_count()) as pool:
        pool.map(worker, (instance for instance in instances))

    # 输出None
    print(instances[0].bar)

问题根源

Python的多进程采用内存隔离机制:子进程会复制主进程的对象副本进行操作,而非直接修改主进程中的原对象。你的worker函数调用instance.put_bar()后,修改的是子进程里的对象副本,主进程中的原对象完全不受影响。另外put_bar()方法没有返回修改后的对象,pool.map()拿到的只是一堆None,自然无法更新原列表里的实例。

解决方案

修改worker函数,让它返回修改后的对象实例,再用pool.map()的结果替换原列表中的对象:

import os
from multiprocessing import Pool


class Foo:

    def __init__(self):
        self.bar = None

    def put_bar(self):
        self.bar = 1.0


def worker(instance):
    instance.put_bar()
    return instance  # 返回修改后的对象


if __name__ == "__main__":

    instances = [Foo() for _ in range(100)]

    with Pool(os.cpu_count()) as pool:
        # 用返回的修改后的对象替换原列表
        instances = pool.map(worker, instances)

    # 输出1.0
    print(instances[0].bar)

补充说明

如果你的Foo类包含大型数据,复制对象会带来额外的内存开销,此时可以考虑使用multiprocessing.Manager创建可共享的对象,或者将属性改为共享内存类型(如multiprocessing.Value)。但对于大多数场景,直接返回修改后的对象是最简单高效的方案。

内容的提问来源于stack exchange,提问作者abc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 19:25:19