2016-02-04 47 views
4

我正在使用多處理來爲我的應用程序創建子進程。 我也在進程和子進程之間共享一本字典。我的代碼不能將項目追加到多處理共享列表

實施例:

主要過程:

from multiprocessing import Process, Manager 
manager = Manager() 
shared_dict = manager.dict() 
p = Process(target=mysubprocess, args=(shared_dict,)) 
p.start() 
p.join() 
print shared_dict 

我的子過程:

def mysubprocess(shared_dict): 
    shared_dict['list_item'] = list() 
    shared_dict['list_item'].append('test') 
    print shared_dict 

在兩種情況下打印的值是: {'list_item': []}

什麼可能是問題? 感謝

回答

7

Manager.dict會給你一個字典,其中直接的變化將在進程之間傳播,但如果你改變包含在字典對象不檢測(如"list_item"下存儲的列表)。見注在SyncManager documentation的底部:

注:的修改可變值或字典和列表代理項目將無法通過管理器來傳播,因爲代理沒有在知道其價值的方式或項目被修改。要修改這樣的項目,您可以將修改的對象重新分配給容器代理。

因此,在您的示例中,當您將該列表設置爲字典時,列表會同步,但附加不會觸發另一個同步。

您可以通過重新分配在字典的關鍵繞開這個問題:

from multiprocessing import Process, Manager 

def mysubprocess(shared_dict): 
    item = shared_dict['list_item'] = list() 
    item.append('test') 
    shared_dict['list_item'] = item 
    print 'subprocess:', shared_dict 

manager = Manager() 
shared_dict = manager.dict() 
p = Process(target=mysubprocess, args=(shared_dict,)) 
p.start() 
p.join() 
print 'main process:', shared_dict 

但如果該列表會長長,這可能會效率低下 - 整個列表將被序列化併發送至管理器進程爲每個追加。在這種情況下,更好的方法是直接使用共享列表SyncManager.list(儘管如果列表元素是可變的,您仍然會遇到同樣的問題 - 您需要在列表中重置它們以在進程之間發送它們) 。

+0

我試圖做到這一點,但沒有再改變... – Dan

+0

我剛試過,它的工作 - 我會更新我的例子與完整的代碼。 – babbageclunk

+0

嗨,謝謝!它現在有效。 另一個小問題...你知道我該如何清除所有的字典(要清除'shared_dict'中的所有鍵和值)? – Dan