我有一个多处理脚本循环遍历字典,如下所示:
jobs = []
for key, val in datadict.items():
jobs.append(pool.apply_async(worker, (val))
pool.close()
pool.join()
jobs
是结果对象的列表,(调用get()
将提供数据列表)
我想格式化结果,使它们是一个字典,其键和顺序与输入字典相同。
我想在完成所有工作后立即执行此操作:
result = {key: jobs[key].get() for key, val in datadict}
这是有效的,因为datadict
中的键是整数(因此可用于索引作业列表)。
但后来我发现,也许最终的工作清单不一定是相同的顺序(因为它是创造的) - 这是真的吗? (我希望订单可能变得混乱,因为一个过程可能比另一个过程更快完成等)
所以我决定将key
datadict
传递给worker函数,然后再将其返回,结果为元组。因此调用jobs[index].get()
将返回一个元组,其中第一个值是键(刚刚通过函数),第二个值是实际结果
result = dict([job.get() for job in jobs])
所以最终的脚本是:
def worker(val, key):
res = "Do something to val"
return (key, res)
if __name__ == "__main__":
jobs = []
for key, val in datadict.items():
jobs.append(pool.apply_async(worker, (val, key))
pool.close()
pool.join()
result = dict([job.get() for job in jobs])
但这是最好的方法吗?有几点让我烦恼:
jobs
列表的结果顺序与输入顺序答案 0 :(得分:2)
显式排序datadict
字典键,并迭代它。
import multiprocessing
def worker(val):
res = "Do something to val {}".format(val)
return res
if __name__ == "__main__":
datadict = {1: 'val1', 2: 'val2', 0: 'val0'}
jobs = []
pool = multiprocessing.Pool()
for key in sorted(datadict): # <------------
jobs.append(pool.apply_async(worker, (datadict[key],)))
pool.close()
pool.join()
result = [job.get() for job in jobs]
print(result)
# ['Do something to val 0', 'Do something to val 1', 'Do something to val 2']
顺便说一句,如果worker
只接受一个参数,则可以使用Pool.map
:
if __name__ == "__main__":
datadict = {1: 'val1', 2: 'val2', 0: 'val0'}
jobs = []
pool = multiprocessing.Pool()
result = pool.map(worker, sorted(datadict)) # <---
pool.close()
pool.join()
答案 1 :(得分:1)
dict
容器不保证任何特定排序。如果您想保留订单,则需要将结果存储在list
:
result = [job.get() for job in jobs]
或者您可以使用OrderedDict来维护广告订单:
result = OrderedDict([job.key, job.get() for job in jobs])
第二种解决方案需要一种从作业中获取密钥的方法。
<强>更新强>:
如果通过密钥给出订单,那么您只需按此属性对结果进行排序(作业需要知道其密钥):
results = [job.get() for job in jobs]
results = sorted(results, key=attrgetter('key'))
或者如果您需要dict
:
results = [job.get() for job in jobs]
results = OrderedDict([job.key, job for job in sorted(results, key=attrgetter('key'))])
答案 2 :(得分:0)
作业可能无序完成,但这不会改变jobs
列表的顺序。但是,您可以通过循环jobs
来填充datadict.items()
;这使得它们处于任意顺序,因为字典不能保持秩序。
将密钥放在jobs
中将是实现您想要的一种方式:
jobs = []
for key, val in datadict.items():
jobs.append((key, pool.apply_async(worker, (val,)))
pool.close()
pool.join()
result = {key: job.get() for key, job in jobs}