Python多处理:检索下一个结果

时间:2017-09-28 18:27:53

标签: python concurrency multiprocessing

我正在尝试找出一种在Python 3.6中使用multiprocessing包来运行一组约100个任务的好方法,其中最多同时运行4个任务。我也想:

  1. 反复从池中获取下一个已完成的任务并处理其返回值,直到所有任务都成功或失败;
  2. 使任何给定任务中的异常非致命,因此我仍然可以访问其他任务的结果。
  3. 我不需要维护提交到池的任务的顺序(即我不需要队列)。任务总数(上面的“100”)并不过分,例如我不介意一次性提交它们并让它们排队等到工人可用。

    我认为multiprocessing.Pool非常适合这种情况,但我似乎找不到可以迭代调用的“获取下一个结果”方法。

    这是否会让我自己从流程管理原语中解脱出来?或者Pool(或我缺少的其他东西)可以支持这个工作流程吗?

    对于上下文,我使用每个工作者调用一个可能需要几分钟的远程进程,并且有能力同时处理N个作业(在我上面的具体例子中为“4”)。

1 个答案:

答案 0 :(得分:0)

我提出了以下模式(使用2名工人和6名工作,而不是4和100):

import random
import time
from multiprocessing import Pool, TimeoutError
from queue import Queue


def worker(x):
    print("Start: {}".format(x))
    time.sleep(5 * random.random())  # Sleep a random amount of time
    if x == 2:
        raise Exception("Two is bad")
    return x


if __name__ == '__main__':

    with Pool(processes=2) as pool:
        jobs = Queue()
        for i in range(6):
            jobs.put(pool.apply_async(worker, [i]))

        while not jobs.empty():
            j = jobs.get(timeout=1)
            try:
                r = j.get(timeout=0.1)
                print("Done: {}".format(r))
            except TimeoutError as e:
                jobs.put(j)  # Not ready, try again later
            except Exception as e:
                print("Exception: {}".format(e))

似乎工作得很好:

Start: 0
Start: 1
Start: 2
Done: 1
Start: 3
Exception: Two is bad
Start: 4
Start: 5
Done: 3
Done: 4
Done: 5
Done: 0

我会看看我是否可以通过一般功能来管理排队。

我认为它的主要缺点是,已完成的工作可能会暂时被忽视,而未完成的工作会被轮询并可能超时。避免这种情况可能需要使用回调 - 如果它成为一个足够大的问题,我可能会将其添加到我的应用程序中。