Python 从不同进程更新相同的实例变量
下面是一个简单的例子:Python 从不同进程更新相同的实例变量,python,multiprocessing,shared-memory,Python,Multiprocessing,Shared Memory,下面是一个简单的例子: class Test: def __init__(self): self.foo = [] def append(self, x): self.foo.append(x) def get(self): return self.foo def process_append_queue(append_queue, bar): while True: x = append_qu
class Test:
def __init__(self):
self.foo = []
def append(self, x):
self.foo.append(x)
def get(self):
return self.foo
def process_append_queue(append_queue, bar):
while True:
x = append_queue.get()
if x is None:
break
bar.append(x)
print("worker done")
def main():
import multiprocessing as mp
bar = Test()
append_queue = mp.Queue(10)
append_queue_process = mp.Process(target=process_append_queue, args=(append_queue, bar))
append_queue_process.start()
for i in range(100):
append_queue.put(i)
append_queue.put(None)
append_queue_process.join()
print str(bar.get())
if __name__=="__main__":
main()
当您在main()
函数的末尾调用bar.get()
时,为什么它仍然返回空列表?如何使子进程也能使用相同的Test
实例而不是新实例
感谢所有答案 通过酸洗对象并将字符串传递到管道上,在进程之间复制对象。对于进程之间的纯Python对象,没有办法实现真正的“共享内存”。要精确实现这种类型的同步,请查看
multiprocessing.Manager
文档(),其中提供了有关常见Python容器类型的同步版本的示例。这些是“代理”容器,在这些容器中,代理上的操作跨进程边界发送所有参数,并进行pickle处理,然后在父进程中执行。通过pickle对象并将字符串传递到管道上,在进程之间复制对象。对于进程之间的纯Python对象,没有办法实现真正的“共享内存”。要精确实现这种类型的同步,请查看multiprocessing.Manager
文档(),其中提供了有关常见Python容器类型的同步版本的示例。这些是“代理”容器,其中代理上的操作跨进程边界发送所有参数,并进行pickle处理,然后在父进程中执行。通常,进程具有不同的地址空间,因此一个进程中对象的突变对任何其他进程中的任何对象都没有影响。需要进行进程间通信,以便将另一个进程中所做的更改告知该进程
这可以显式地(使用多处理.Queue
之类的方法)完成,如果您为此目的使用了由多处理
实现的工具,则可以隐式地完成。例如,大量工作都是在幕后进行的,以使多处理.Queue
在进程间可见
在您的特定示例中,最简单的方法是将\uuuuu init\uuuu
函数替换为如下所示:
def __init__(self):
import multiprocessing as mp
self.foo = mp.Manager().list()
碰巧,mp.Manager
实例支持一个list()
方法,该方法创建一个进程感知列表对象(实际上是列表对象的代理,它将列表操作转发给一个后台服务器进程,该进程维护“real”的一个副本)列表-列表对象并不是真正跨进程共享的,因为这是不可能的-但是代理使它看起来是共享的)
因此,如果您进行了更改,您的代码将显示您期望的结果-没有更简单的方法
请注意,您需要的IPC(进程间通信)越少,多处理的效果越好,无论应用程序或编程语言如何,这一点都是正确的。一般来说,进程有不同的地址空间,因此一个进程中对象的突变对任何其他进程中的任何对象都没有影响。需要进行进程间通信,以便将另一个进程中所做的更改告知该进程 这可以显式地(使用
多处理.Queue
之类的方法)完成,如果您为此目的使用了由多处理
实现的工具,则可以隐式地完成。例如,大量工作都是在幕后进行的,以使多处理.Queue
在进程间可见
在您的特定示例中,最简单的方法是将\uuuuu init\uuuu
函数替换为如下所示:
def __init__(self):
import multiprocessing as mp
self.foo = mp.Manager().list()
碰巧,mp.Manager
实例支持一个list()
方法,该方法创建一个进程感知列表对象(实际上是列表对象的代理,它将列表操作转发给一个后台服务器进程,该进程维护“real”的一个副本)列表-列表对象并不是真正跨进程共享的,因为这是不可能的-但是代理使它看起来是共享的)
因此,如果您进行了更改,您的代码将显示您期望的结果-没有更简单的方法
请注意,所需的IPC(进程间通信)越少,多处理效果越好,无论应用程序或编程语言如何,这一点都是正确的