Python 在从多处理收集结果时确保正确的顺序
我有一个多处理脚本,它在字典上循环,如下所示:Python 在从多处理收集结果时确保正确的顺序,python,python-2.7,dictionary,multiprocessing,Python,Python 2.7,Dictionary,Multiprocessing,我有一个多处理脚本,它在字典上循环,如下所示: jobs = [] for key, val in datadict.items(): jobs.append(pool.apply_async(worker, (val)) pool.close() pool.join() result = dict([job.get() for job in jobs]) jobs是一个结果对象列表(其中调用get()将给出一个数据列表) 我想格式化结果,使其成为一个与输入字典具有相同键和顺序的字
jobs = []
for key, val in datadict.items():
jobs.append(pool.apply_async(worker, (val))
pool.close()
pool.join()
result = dict([job.get() for job in jobs])
jobs
是一个结果对象列表(其中调用get()
将给出一个数据列表)
我想格式化结果,使其成为一个与输入字典具有相同键和顺序的字典
我想在所有工作完成后简单地这样做:
result = {key: jobs[key].get() for key, val in datadict}
这是因为datadict
中的键是整数(因此可用于索引作业列表)。
但是,我突然想到,可能生成的作业列表的顺序不一定与创建的顺序相同——这是真的吗?(我预计订单可能会变得混乱,因为一个流程可能比另一个流程完成得更快等)
因此,我决定将datadict
的键
传递到worker函数中,并将结果作为元组再次返回。因此,调用jobs[index].get()
将返回一个元组,其中第一个值是键(刚刚通过函数),第二个值是实际结果
然后我可以创建一个字典,如下所示:
jobs = []
for key, val in datadict.items():
jobs.append(pool.apply_async(worker, (val))
pool.close()
pool.join()
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])
但这是最好的方法吗?有两点让我感到困扰:
作业
列表的结果顺序与输入顺序匹配对
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']
作业可能会按顺序完成,但这不会改变
作业
列表的顺序。但是,您可以通过循环datadict.items()
来填充作业
;这就把它们按任意顺序排列,因为字典不维持顺序
将钥匙放入作业中
将是实现您所需的一种方法:
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}
dict
容器不保证任何特定的订购。如果要使事情保持有序,您需要将结果存储在列表中
:
result = [job.get() for job in jobs]
或者,您可以使用维护插入顺序的:
result = OrderedDict([job.key, job.get() for job in jobs])
第二种解决方案需要一种从作业中获取密钥的方法
更新::
如果顺序是按键给出的,那么您可以按此属性对结果进行排序(作业需要知道其键):
或者,如果您需要一个命令
:
results = [job.get() for job in jobs]
results = OrderedDict([job.key, job for job in sorted(results, key=attrgetter('key'))])
这是怎么回事?假设我的字典中有两个项目,如果第二个项目首先完成,它是否会在第一个项目之前附加到作业列表中(因此位于错误的位置)?您将结果对象附加到
jobs
for循环中的您自己。之后没有任何东西会重新排列它们。对结果对象调用get
,等待实际结果到达,但不会更改列表的顺序。。。也许“秩序”这个词用错了。我需要将正确的结果分配给正确的键。