Python多进程Queue传递嵌套类对象异常及原理咨询
问题解答
1. 错误原因与修复方案
你遇到的问题核心是ParentData中的childData是类属性,而非实例属性。
在你的代码里,ParentData类定义时直接给childData赋值了ChildData(),这会让所有ParentData实例共享同一个类级别的ChildData对象。当你在Sender进程里修改dataToSend.childData.testBool = True时,本质是修改了类属性,但进程间内存完全隔离,这个修改无法传递到Receiver进程。Receiver进程从队列反序列化ParentData对象时,会重新从ParentData类中读取默认的childData(也就是testBool为False的初始状态)。
修复方法很简单,把childData改成实例属性,在ParentData的__init__方法里初始化:
class ParentData: testBool: bool = False def __init__(self): self.childData = ChildData() # 每个实例拥有独立的ChildData对象
修改后的完整代码:
import multiprocessing class ChildData: testBool: bool = False testInt1: int = 20 testInt2: int = 6500 class ParentData: testBool: bool = False def __init__(self): self.childData = ChildData() class Reciever: queue: multiprocessing.Queue def __init__(self, queue): self.queue = queue def run(self): queueValue = self.queue.get() print(queueValue.testBool) print(queueValue.childData.testBool) class Sender: queue: multiprocessing.Queue def __init__(self, queue): self.queue = queue def run(self): dataToSend = ParentData() dataToSend.testBool = True dataToSend.childData.testBool = True self.queue.put(dataToSend) queue = multiprocessing.Queue() reciever = Reciever(queue) recieverProcess = multiprocessing.Process( target = reciever.run ) recieverProcess.start() sender = Sender(queue) senderProcess = multiprocessing.Process( target = sender.run ) senderProcess.start()
运行后就能得到你预期的输出:
True True
2. Queue传递对象的本质
multiprocessing的Queue传递的是对象副本。
进程之间内存是完全隔离的,Queue会使用pickle模块把对象序列化成字节流,发送到队列中;接收方进程再把字节流反序列化成一个全新的对象。这个新对象和原对象没有任何关联,修改副本不会影响发送进程中的原对象,完全符合你需要传递副本的需求。
内容的提问来源于stack exchange,提问作者Andrew Cornford
相关产品推荐
相关产品推荐

