2015-04-01 389 views
2

這可能不是它的預期用途,但我想知道如何使用多維的manager.list()。我可以創建就好了,這樣的事情:Python:使用多維multiprocessing.manager.list()

from multiprocessing import manager 

test = manager.list(manager.list()) 

然而當過我嘗試訪問它會返回元素的值,而不是它的代理對象測試列表的第一個元素

test[0] # returns [] and not the proxy, since I think python is running __getitem__. 

是無論如何,我可以解決這個問題,並以這種方式使用manager.list()?

+0

是否有任何理由爲什麼你使用嵌套manager.list()?我想使用manager.list()返回列出的對象嗎? – ha9u63ar 2015-04-01 14:01:14

+0

@ ha9u63ar我需要一個manager.list()的列表來完成我的任務。 – user2909415 2015-04-01 14:07:37

回答

1

multiprocessing documentation對此有一張紙條:

注意

的修改可變值或字典和列表代理項目將 不通過管理器來傳播,因爲代理沒有方式 知道它的值或項目何時被修改。要修改這樣一個項目, 你可以重新修改的對象到容器代理:

# 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是因爲酸洗代理是如何工作的。 BaseProxy.__reduce__創建了一個RebuildProxy對象,該對象實際上用於取消打開ProxyRebuildProxy看起來是這樣的:

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) 

由於文檔字符串說,如果在unpickle被管理服務器的內部存在的,創建實際的共享對象,而不是Proxy它。這可能是一個bug,並且there is actually one filed已經對此行爲了。

+0

感謝您的回答,但我已經瞭解了代理名單。我的問題真正想知道的是如何取回代理對象,當我調用test [0]而不是代理保存的值時,代理對象保存我的列表。 – user2909415 2015-04-01 14:22:13

+0

@ user2909415我很確定內部列表不會獲取代理對象,它們只是存儲爲標準列表。讓我仔細檢查代碼並更新我的答案。 – dano 2015-04-01 14:25:28

+0

@ user2909415我在'multiprocessing'代碼中添加了一些工具,用於驗證當通過'_callmethod'向服務器發送代理對象時,所指對象(例如,底層列表)最終都會被服務器接收。儘管如此,我還是無法確定爲什麼會發生這種情況。 – dano 2015-04-01 16:12:14