Python:使用多维多处理.manager.list()函数

Python:使用多维多处理.manager.list()函数,python,multidimensional-array,multiprocessing,Python,Multidimensional Array,Multiprocessing,这可能不是它的预期用途,但我想知道如何使用多维管理器.list()。我可以很好地创建,比如: from multiprocessing import manager test = manager.list(manager.list()) def RebuildProxy(func, token, serializer, kwds): ''' Function used for unpickling proxy objects. If possible the sha

这可能不是它的预期用途,但我想知道如何使用多维管理器.list()。我可以很好地创建,比如:

from multiprocessing import manager

test = manager.list(manager.list())
def RebuildProxy(func, token, serializer, kwds):
    '''
    Function used for unpickling proxy objects.

    If possible the shared object is returned, or otherwise a proxy for it.
    '''
    server = getattr(process.current_process(), '_manager_server', None)

    if server and server.address == token.address:
        return server.id_to_obj[token.id][0]
    else:
        incref = (
            kwds.pop('incref', True) and
            not getattr(process.current_process(), '_inheriting', False)
            )
        return func(token, serializer, incref=incref, **kwds)
但是,当我尝试访问测试列表的第一个元素时,它返回该元素的值,而不是它的代理对象

test[0]  # returns [] and not the proxy, since I think python is running __getitem__.
我是否可以绕过这个问题,以这种方式使用manager.list()?

有一个注意事项:

注意

将修改dict和list代理中的可变值或项目 无法通过管理器传播,因为代理无法 知道其值或项目何时被修改。要修改此项, 可以将修改后的对象重新指定给容器代理:

# create a list proxy and append a mutable object (a dictionary) 
lproxy = manager.list() 
lproxy.append({})
# now mutate the dictionary 
d = lproxy[0]
d['a'] = 1 
d['b'] = 2
# at this point, the changes to d are not yet synced, but by
# reassigning the dictionary, the proxy is notified of the change 
lproxy[0] = d
因此,使用多维列表的唯一方法是将对列表第二维度所做的任何更改重新分配给顶级列表,而不是:

test[0][0] = 1
你可以:

tmp = test[0]
tmp[0] = 1
test[0] = tmp
这不是最令人愉快的方式,但您可能可以编写一些帮助函数,使其更容易接受

编辑:

当您将一个
ListProxy
附加到另一个
ListProxy
时,返回一个普通列表的原因似乎是因为pickle代理的工作方式
BaseProxy.\uuu reduce\uuu
创建一个
RebuildProxy
对象,该对象实际上用于取消勾选
代理
<代码>重建氧气如下所示:

from multiprocessing import manager

test = manager.list(manager.list())
def RebuildProxy(func, token, serializer, kwds):
    '''
    Function used for unpickling proxy objects.

    If possible the shared object is returned, or otherwise a proxy for it.
    '''
    server = getattr(process.current_process(), '_manager_server', None)

    if server and server.address == token.address:
        return server.id_to_obj[token.id][0]
    else:
        incref = (
            kwds.pop('incref', True) and
            not getattr(process.current_process(), '_inheriting', False)
            )
        return func(token, serializer, incref=incref, **kwds)

正如docstring所说,如果取消勾选发生在manager服务器内部,则会创建实际的共享对象,而不是它的代理。这可能是一个bug,并且已经针对这种行为。

您使用嵌套管理器.list()有什么原因吗?我以为使用manager.list()会返回列出的对象?@ha9u63ar我需要一个manager.list()列表来完成我的任务。谢谢你的回答,但我已经了解了代理列表。我的问题真正想知道的是,当我调用test[0]时,如何取回保存我列表的代理对象,而不是代理所保存的值。@user2909415我很确定内部列表没有获取代理对象,它们只是作为标准列表存储。让我在代码中再次检查并更新我的答案。@user2909415我在
多处理
代码中添加了一些指令,用于验证当您通过
\u callmethod
向服务器发送代理对象时,引用对象(例如底层列表)是服务器最终接收到的所有对象。不过,我还不能确定发生这种情况的原因。所以我想在我的情况下,最简单的事情就是创建一个我自己的代理类,该类保存一个代理列表,并将其注册到我自己的经理处,然后以这种方式使用它。我真希望多处理能像python的其他部分一样易于使用…@user2909415看起来这是一个bug:。问题是,当您在manager服务器中取消勾选代理时,您将获得引用对象本身,而不是代理。因此,当管理器被传递一个代理并去取消勾选它时,它将以引用对象而不是代理本身结束。如果您确实希望保留代理对象,以便以后可以获取它,那么这就是一个问题。