共享内存值从对象中消失

Shared memory Value dissapears from an object

Python(2.7.9,Windows)中有一些奇怪的行为,想请教一下。

我试图在初始化时用一个变量扩展 class,我想在两个进程(父进程和子进程)之间共享这个 class 的一个对象。他们俩都会用到这个变量。

这段代码工作正常:

# coding: utf-8
from multiprocessing import Process, Value
from time import sleep


class ExQueue(object):
    def __init__(self, *args, **kwargs):
        super(ExQueue, self).__init__(*args, **kwargs)
        self.trust_me_this_name_is_unique = Value('L', 0)


def func(ex_queue):
    print 'I am the child process. Is there a parameter: ',
    print hasattr(ex_queue, 'trust_me_this_name_is_unique')

    # this sleep is here to assure no printing overlapping
    sleep(.5)

def main():
    ex_queue = ExQueue()

    print 'I am the parent process. Is there a parameter: ',
    print hasattr(ex_queue, 'trust_me_this_name_is_unique')

    child_process = Process(target=func, args=(ex_queue,))

    child_process.start()

    child_process.join()

    print 'I am the parent process. Is there a parameter: ',
    print hasattr(ex_queue, 'trust_me_this_name_is_unique')

if __name__ == '__main__':
    main()

输出:

I am the parent process. Is there a parameter:  True
I am the child process. Is there a parameter:  True
I am the parent process. Is there a parameter:  True

但是如果 ExQueue 继承自 Queue class(来自 multiprocessing.queues 模块的那个),这个技巧就不起作用了。

开头加上:

from multiprocessing.queues import Queue

并改变

class ExQueue(object):

至:

class ExQueue(Queue):

输出将是:

I am the parent process. Is there a parameter:  True
I am the child process. Is there a parameter:  False
I am the parent process. Is there a parameter:  True

因此,在子进程的 ExQueue 示例中没有 trust_me_this_name_is_unique 变量。

对我做错了什么有什么想法吗?

谢谢!

UPD: 在 Mac OS 上按预期工作。变量不消失。

解决方案

谢谢你,tdelaney!您的回答帮了大忙!

我将这两种方法添加到 ExQueue,它现在可以在 Windows 上腌制了:

def __getstate__(self):
    state = super(ExQueue, self).__getstate__()
    return state + (self.trust_me_this_name_is_unique,)

def __setstate__(self, state):
    state, self.trust_me_this_name_is_unique = state[:-1], state[-1]
    super(ExQueue, self).__setstate__(state)

仍然不确定从 Queue 继承是否是一个好方法。 :)

这不是共享内存值的问题,是队列 object 上的变量本身消失了。

多处理在实现 *nix 分叉模型和 Windows create-process 模型的机器上的工作方式不同。在 *nix 上,当您创建 multiprocessing 进程时,parent 进程被分叉,并且由于 child 具有 copy-on-write 视图 parent 的内存space,所有 python object(包括您的队列)都在 child space 中,可以使用了。

在Windows,没有fork。创建了一个新进程,parent 进程的相关部分被 pickle,发送到 child 并 unpickled。这仅适用于 picklable objects,因此在 linux 中工作的代码可能在 windows.

中失败

如果您有一个 object 本身不可挑选,您可以实施 __getstate____setstate__ 方法,return object 的一个可挑选子集=] 并从该状态重建 object。这是用 multiprocessing.Queue object 完成的。它不在 __getstate__ 中包含您的变量,因此变量在重新创建时不包含在 child object 中。

一个简单的解决方案是将您的数据放在其他地方。如果这不可行,请创建您自己的 multiprocessing.Queue 子类并编写您自己的 __getstate____setstate__ 方法。