python executor从完成的回调中生成任务(递归提交任务)

时间:2018-08-16 14:09:06

标签: python multithreading multiprocessing

我正在尝试从完成的任务的结果中提交其他任务:

with concurrent.futures.ThreadPoolExecutor() as executor:
    future = executor.submit(my_task)
    def callback(future):
        for another_task in future.result():
            future = executor.submit(another_task)
            future.add_done_callback(callback)
    future.add_done_callback(callback)

但是我得到了:

  

RuntimeError:关机后无法安排新的期货

使执行程序保留用于回调的最佳方法是什么?信号量?

理想情况下,如果将ThreadPoolExecutor替换为ProcessPoolExecutor,解决方案应该可以很好地转移。

2 个答案:

答案 0 :(得分:2)

callback在单独的线程中执行。因此,当您的回调逻辑开始执行时,主循环很有可能会使上下文管理器关闭Executor。这就是为什么您观察RuntimeError的原因。

最简单的修复是按顺序运行您的逻辑。

futures = []

with concurrent.futures.ThreadPoolExecutor() as pool:
    futures.append(pool.submit(task))

    while futures:
        for future in concurrent.futures.as_completed(futures):
            futures.remove(future)

            for new_task in future.result():
                futures.append(pool.submit(new_task))

请注意,此代码可能会导致任务以指数形式提交给Executor

答案 1 :(得分:0)

保证该解决方案可以在任何给定时间点最大限度地利用处理能力。 sleep的使用并不那么优雅,但这是我到目前为止最好的。

with concurrent.futures.ThreadPoolExecutor() as executor:
    pending_tasks = 1
    future = executor.submit(my_task)
    def callback(future):
        nonlocal pending_tasks
        for another_task in future.result():
            pending_tasks += 1
            future = executor.submit(another_task)
            future.add_done_callback(callback)
        pending_tasks -= 1
    future.add_done_callback(callback)
    while pending_tasks:
        time.sleep(10)