Python:等待所有`concurrent.futures.ThreadPoolExecutor`的未来

时间:2014-01-15 16:40:29

标签: python concurrency future

我已经给了concurrent.futures.ThreadPoolExecutor一堆任务,我想等到它们全部完成后再继续流程。我怎么能这样做,而不必保存所有的期货并打电话给wait? (我想对执行者采取行动。)

3 个答案:

答案 0 :(得分:25)

只需致电Executor.shutdown

  

<强> shutdown(wait=True)

     

告知执行者它应该释放它所有的资源   在当前待处理的期货执行时使用。呼叫   在关机后制作Executor.submit()Executor.map()   提高RuntimeError

     

如果等待True,那么在所有未决期货到期之前,此方法不会返回   完成执行并释放与执行程序关联的资源。

但是,如果您在列表中跟踪您的未来,那么您可以避免使用futures.wait()函数关闭执行程序以备将来使用:

  

<强> concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)

     

等待Future个实例(可能由不同的实例创建)   由Executor完成的fs个实例)。返回一个命名的2元组   集合。名为done的第一组包含期货   在等待完成之前完成(完成或取消)。该   名为not_done的第二组包含未完成的期货。

请注意,如果您未提供timeout,则等待所有期货完成。

您也可以使用futures.as_completed(),但是您必须迭代它。

答案 1 :(得分:8)

Bakuriu的回答是正确的。只是延伸一点点。我们都知道上下文管理器有__enter____exit__方法。以下是class Executor ThreadPoolExecutor的基类)的定义方式

class Executor(object):

    # other methods

    def shutdown(self, wait=True):
        """Clean-up the resources associated with the Executor.

        It is safe to call this method several times. Otherwise, no other
        methods can be called after this one.

        Args:
            wait: If True then shutdown will not return until all running
                futures have finished executing and the resources used by the
                executor have been reclaimed.
        """
        pass

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown(wait=True)
        return False

实际定义ThreadPoolExecutor方法

的是shutdown
class ThreadPoolExecutor(_base.Executor):
    def shutdown(self, wait=True):
        with self._shutdown_lock:
            self._shutdown = True
            self._work_queue.put(None)
        if wait:
            for t in self._threads:
                t.join()

答案 2 :(得分:0)

如前所述,可以使用Executor.shutdown(wait=True),但也请注意文档中的以下注意事项:

如果使用with语句,可以避免显式调用此方法,这将关闭Executor(等待Executor.shutdown()被调用将 wait 设置为True):

import shutil
with ThreadPoolExecutor(max_workers=4) as e:
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
    e.submit(shutil.copy, 'src4.txt', 'dest4.txt')