在多处理池中处理multiprocessing.TimeoutError.map_async()

时间:2016-05-30 13:36:43

标签: python python-multiprocessing

到目前为止,我这样做了:

rets=set(pool.map_async(my_callback, args.hosts).get(60*4))

如果超时,我得到一个例外:

 File "/usr/lib/python2.7/multiprocessing/pool.py", line 524, in get
    raise TimeoutError
multiprocessing.TimeoutError

我想优雅地处理这个问题:

我可以访问的所有主机的输出应该进入rets,所有超时的主机应该进入单独的列表。

怎么可以这样做?

1 个答案:

答案 0 :(得分:6)

据我所知,你不能,或者至少不在map_asyncmap_async是一种解决特定用例特定问题的便捷方法,并且与您所获得的内容不匹配,因为您需要更精细的控制。

但是,您仍然可以这样做,您只需要在多处理模块中使用更细粒度的方法。特别是,您可以使用apply_async动态地向池中添加作业,这使您可以更好地控制如何处理单个任务的成功和失败。

下面是一个非常简单的例子,我认为你做了什么:

from multiprocessing.pool import Pool, TimeoutError
from time import sleep, time


def task_function(xx):
    print('Task %d running' % xx)
    sleep(xx)
    print('Task %d ended' % xx)
    return 'Result of task %d' % xx

pl = Pool()
results = [
    pl.apply_async(task_function, (_xx,)) 
    for _xx in range(10)]

start = time()
wait_until = start + 5

rets = []
timed_out_results = []

for res in results:
    timeout = wait_until - time()
    if timeout < 0:
        timeout = 0

    try:
        rets.append(res.get(timeout))
    except TimeoutError:
        timed_out_results.append(res)

print('%s ended' % (rets,))
print('%s timedout' % (timed_out_results,))

这会运行10个作业,打印一行,睡眠,然后打印另一行。第一个睡眠为0秒,下一个为1,下一个为2等。我们在5秒后超时,因此我们预计5个任务已完成,5个任务已超时。

请注意我还没有停止仍在运行的任务,因此在现实世界中,它们可以在打印结果所需的时间内继续并完成。你必须弄清楚你对此有多关心/该怎么做。