Windows下新Process无法获取更新后类属性值的问题排查
Windows下多进程无法获取更新后类属性的原因解析
问题现象
先看代码及对应输出:
class A: a1 = {} def fp(a): print(a.a1) if __name__ == '__main__': a = A() A.a1.update({"p":"1"}) # 更新类变量 p1 = Process(target=fp, args=(a,)) p1.start() A.a1 = {"p":"2"} # print('--', a.a1) # {'p': '2'} p2 = Process(target=fp, args=(a,)) p2.start() a.a1 = {"p":"3"} # 不会修改A.a1 # print('--', A.a1) # {'p': '2'} p3 = Process(target=fp, args=(a,)) p3.start()
输出结果:
{} {} {'p': '3'}
核心原因:Windows的进程创建机制
Windows系统中,Python的multiprocessing.Process创建子进程时,不会像Linux那样通过fork复制父进程内存空间,而是启动全新的Python解释器,重新导入当前模块。
这意味着:子进程启动时,模块内的类定义会被重新执行,类属性会被重置为定义时的默认值(即A.a1 = {})。父进程对类属性的所有修改,都无法被子进程感知——因为二者的类属性属于不同内存空间的独立对象。
逐案例解析
案例1:A.a1.update({"p":"1"})
父进程通过update修改了类属性A.a1的内容,但子进程启动时重新初始化类属性为{},因此打印空字典。
案例2:A.a1 = {"p":"2"}
父进程给类属性A.a1重新赋值了新字典,但子进程依然会将类属性重置为初始的{},所以打印结果还是空字典。
案例3:a.a1 = {"p":"3"}
这一操作并非修改类属性,而是给实例a新增了实例属性a1(类属性仍为{"p":"2"})。当实例a被传递给子进程时,Python会通过pickle序列化实例,实例属性会被一并传递。子进程反序列化得到实例后,访问a.a1会优先读取实例属性,因此打印{'p': '3'}。
相关错误说法纠正
部分资料提到“用instance.attr=设置类成员”是错误的——instance.attr=只会给当前实例添加或覆盖实例属性,完全不会修改类本身的属性。只有Class.attr=的方式能修改类属性,但这种修改在Windows多进程场景下无法被子进程继承。
内容的提问来源于stack exchange,提问作者TurtleTread
相关产品推荐
相关产品推荐

