无法使用多处理经理.dict()共享对象实例

2024-03-29 06:26:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我在与multiprocessing共享对象实例字典时遇到问题。我试图使用一个dict,它被manager共享,但是当我试图使用对象实例作为键时,它会被复制。在

import multiprocessing

class Dog():
    def __init__(self, name = "joe"):
        self.name = name
    def bark(self):
        print("woof")

mg = multiprocessing.Manager()
dt = mg.dict()
dt["a"] = 1
dt["b"] = 2
# As expected
print(dt.items()) # => [('a', 1), ('b', 2)]
dt = mg.dict()
lab = Dog("carl")
print(lab) # => <__main__.Dog instance at 0x7f8d6bb869e0>
dt[lab] = 1
# But then I don't get the ID I expect
print(dt.items()) # => [(<__main__.Dog instance at 0x7f8d6bb86908>, 1)]

我知道解决这个问题的方法是使用对象ID作为键,但是为什么会发生这种情况呢?使用对象ID是解决我问题的最佳方法吗?我注意到,普通的非managerdict()对象不会发生这种情况。在

In the documentation for ^{},我读到一些问题是通知服务器更改,所以我将代码改为这样,但我仍然有同样的问题,我的狗被复制,而不是引用。在

^{pr2}$

Tags: 对象实例nameselfidmaindeflab
2条回答

the documentation on managers所述:

Modifications to mutable values or items in dict and list proxies will not be propagated through the manager, because the proxy has no way of knowing when its values or items are modified. To modify such an item, you can re-assign the modified object to the container proxy

尽管multiprocessing使多个进程之间的通信变得容易,但它仍然不能执行操作系统不允许的操作(访问另一个进程的内存)。实际上,Manager的工作是处理对象的副本,这些副本在需要时被序列化。在

I understand the way to work around this is to use object ID as a key

请注意,您将无法在其他进程中获取这些对象实例。 “正确”的方法是在更改对象时重新指定它们。在

当您创建multiprocessing.Manager时,将产生一个单独的服务器进程,该进程负责托管Manager创建的所有对象。因此,为了将Dog实例存储在Managerdict中,需要对该实例进行pickle并将其发送到Manager进程。当然,这会导致在Manager进程中创建一个完全独立的Dog实例,因此它的ID将与父进程中的Dog实例的ID不匹配。除了在Manager中创建Dog实例作为Proxy实例之外,没有其他方法可以避免:

import multiprocessing
from multiprocessing.managers import SyncManager


def Manager():
    m = SyncManager()
    m.start()
    return m

class Dog():
    def __init__(self, name = "joe"):
        self.name = name
    def bark(self):
        print("woof")

SyncManager.register("Dog", Dog)

mg = Manager()
dt = dict()
lp = mg.list()
lp.append(dt)
print(lp)
dt["a"] = 1 
dt["b"] = 2 
lp[0] = dt
print(lp)
dt = dict()
lab = mg.Dog("carl")
print(lab)
pup = mg.Dog("steve")
print(pup)
dt[lab] = 1 
dt[pup] = 2 
lp[0] = dt
# Their ids don't change
print(lp) 

输出:

^{pr2}$

请记住,这将使对父进程中的Dog实例的所有访问变慢,因为它们现在需要对Manager进程进行IPC调用。在

相关问题 更多 >