【问题标题】:Modify a list in Multiprocessing pool's manager dict修改多处理池的管理器字典中的列表
【发布时间】:2016-12-06 19:58:54
【问题描述】:

我有一个元素列表,我正在多处理 apply_async 任务中处理这些元素,并使用我想要映射整个列表的 manager dict 中的键逐个更新处理的元素。

我尝试了以下代码:

#!/usr/bin/python

from multiprocessing import Pool, Manager

def spammer_task(d, my_list):
    #Initialize manager dict
    d['task'] = {
        'processed_list': []
    }

    for ele in my_list:
        #process here
        d['task']['processed_list'].append(ele)

    return

p = Pool()
m = Manager()
d = m.dict()

my_list = ["one", "two", "three"]

p.apply_async(spammer_task (d, my_list))
print d

最后,它只是在 dict 中发布空列表。 输出:

{'task': {'processed_list': []}}

现在经过一番研究,我知道 manager dict 中的元素变得不可变,因此您必须使用新数据重新初始化整个 dict 才能更新它。所以我尝试了以下代码,它给出了一个奇怪的错误。

#!/usr/bin/python

from multiprocessing import Pool, Manager

def spammer_task(d, my_list):
    #Initialize manager dict
    d['task'] = {
        'processed_list': []
    }

    for ele in my_list:
        #process here
        old_list = d['task']['processed_list']
        new_list = old_list.append(ele)
        #Have to do it this way since elements inside a manager dict become
        #immutable so
        d['task'] = {
            'processed_list': new_list
        }

    return

p = Pool()
m = Manager()
d = m.dict()

my_list = ["one", "two", "three"]

p.apply_async(spammer_task (d, my_list))
print d

输出:

Traceback(最近一次调用最后一次):文件“./a.py”,第 29 行,in p.apply_async(spammer_task (d, my_list)) 文件“./a.py”,第 14 行,在 spammer_task new_list = old_list.append(ele) AttributeError: 'NoneType' 对象没有属性 'append'

不知何故,它似​​乎将None 附加到我无法弄清楚原因的列表中。

【问题讨论】:

  • 也许这只是一个愚蠢的问题,但对我来说,使用 imap 看起来你的例子会更好 - 为什么你使用 apply_async 代替?
  • 这只是一个示例程序,主要的一个使用 apply_async 来完成它正在做的一些事情。此外,它正在调用多个进程
  • 更准确地说——我的意思是使用 Pool.imap 来拥有多个进程并在主进程中修改 dict,因为这在计算上不应该是昂贵的。这对我来说似乎比制作大量副本和额外同步更明智
  • 请用 poc janbrohi 展示一个 sn-p

标签: python dictionary multiprocessing python-multiprocessing multiprocessing-manager


【解决方案1】:

根据https://bugs.python.org/issue6766的解决方案

以下代码修复它,复制整个任务字典,然后修改它并重新复制它

#!/usr/bin/python

from multiprocessing import Pool, Manager

def spammer_task(d, my_list):
    #Initialize manager dict
    d['task'] = {
        'processed_list': []
    }

    for ele in my_list:
        #process here
        foo = d['task']
        foo['processed_list'].append(ele)
        d['task'] = foo
    return

p = Pool()
m = Manager()
d = m.dict()

my_list = ["one", "two", "three"]

p.apply_async(spammer_task (d, my_list))
print d

输出:

{'task': {'processed_list': ['one', 'two', 'three']}}

【讨论】:

    【解决方案2】:

    除了确保d在打印时确实包含某些内容外,结果仍然是{'task': {'processed_list': ['one', 'two', 'three']}}

    #!/usr/bin/python
    
    from multiprocessing import Pool
    
    def spammer_task(my_list):
        #Initialize manager dict
        out= {
            'processed_list': []
        }
    
        for ele in my_list:
            #process here
            out['processed_list'].append(ele)
    
        return 'task',out
    
    
    
    my_list = ["one", "two", "three"]
    
    if __name__=="__main__":
    
        p = Pool()
        d=dict(p.imap_unordered(spammer_task, [my_list])) #this line blocks until finished
        print d
    

    【讨论】:

    • 我不想阻止执行。进程需要在后台运行。
    猜你喜欢
    • 2021-04-26
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 2013-12-23
    • 2020-12-03
    相关资源
    最近更新 更多