共享内存值从对象中消失
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__
方法。
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__
方法。