我正在尝试使用processing.Manager在进程之间共享数据(processing.Manager.list,processing.Manager.dict,...)。但是,当我使用它时,对象是重复的:
from multiprocessing import Process, Manager
def manipulate_in_process(objects):
objs = []
for obj in objects:
objs.append(obj)
print('foo objs', objs)
def do_in_process(objects):
print('objects', objects)
manipulate_in_process(objects)
if __name__ == '__main__':
manager = Manager()
objects = [object(), object()]
print('main objects', objects)
shared_objects = manager.list(objects)
process = Process(target=do_in_process, args=(shared_objects,))
process.start()
process.join()
print('finish')
输出:
main objects [<object object at 0xb72a64a8>, <object object at 0xb72a64b0>]
objects [<object object at 0xb72a64a8>, <object object at 0xb72a64b0>]
foo objs [<object object at 0xb72a64e8>, <object object at 0xb72a64c0>]
finish
使用时共享对象重复: 0xb72a64a8 != 0xb72a64e8 。
答案 0 :(得分:0)
在进程之间复制而不是共享对象几乎是固有的。这是单独进程的定义:它们具有单独的堆与单独的对象。
如果您想要实际的共享数据,则必须使用Value
,Array
或sharedctypes
- 当然,在这种情况下,您只能使用“原生”值和那些你可以表达的C结构。而且,即便如此,也不能保证id
在整个流程中是相同的,只是价值本身就是。
Manager
的要点是,您可以在服务器进程中放置一个对象,例如list
,并在每个子进程中放置该对象的代理。就核心列表功能而言,列表代理看起来像一个真实的列表(迭代,索引,append
,insert
,index
等等。但是代理并没有试图伪造像id
那样的“隐蔽”内省功能。
开箱即用的Manager
可以代理的确切类型列表在Python版本之间有所不同,但您可以在您的版本的文档中找到它。自3.4起,它包含list
,dict
,Namespace
,Lock
,RLock
,Semaphore
,BoundedSemaphore
,{{ 1}},Condition
,Event
,Barrier
,Queue
和Value
。无论如何,它永远不会包含Array
,因为object
除了隐藏的东西之外没有功能。
当然,您可以使用自定义代理object
注册自己的类型。但我不确定您要与Manager
分享的内容。
有关详细信息,请参阅Sharing state between processes;有关详细信息,请参见Managers。