Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从不同进程更新相同的实例变量_Python_Multiprocessing_Shared Memory - Fatal编程技术网

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(进程间通信)越少,多处理效果越好,无论应用程序或编程语言如何,这一点都是正确的