Python: Espera en todos los futuros de `concurrent.futures.ThreadPoolExecutor`

He asignado concurrent.futures.ThreadPoolExecutor un montón de tareas, y quiero esperar hasta que se hayan completado antes de continuar con el flujo. ¿Cómo puedo hacer eso, sin tener que guardar todos los futuros y llamar en wait ? (Quiero una acción sobre el ejecutor.)

Simplemente llame a Executor.shutdown :

shutdown(wait=True)

Indique al ejecutor que debe liberar todos los recursos que esté utilizando cuando se hayan ejecutado los futuros pendientes . Las llamadas a Executor.submit() y Executor.map() realizadas después del cierre generarán RuntimeError .

Si la espera es True , este método no volverá hasta que todos los futuros pendientes se hayan ejecutado y los recursos asociados con el ejecutor hayan sido liberados.

Sin embargo, si mantiene un registro de sus futuros en una lista, puede evitar cerrar el ejecutor para su uso futuro utilizando la función de futures.wait() :

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

Espere las instancias Future (posiblemente creadas por diferentes instancias de Executor ) dadas por fs para completar. Devuelve un conjunto de 2 tuplas de conjuntos. El primer conjunto, con el nombre de hecho, contiene los futuros que se completaron (terminaron o se cancelaron) antes de que se completara la espera. El segundo conjunto, llamado not_done, contiene futuros no completados.

tenga en cuenta que si no proporciona un timeout espera, esperará hasta que se hayan completado todos los futuros.

También puedes usar futures.as_completed() lugar, sin embargo deberías iterar sobre él.

La respuesta de Bakuriu es correcta. Sólo para extender un poco. Como todos sabemos, un administrador de contexto tiene el método __enter__ y __exit__ . Aquí es cómo se define la class Executor ( clase base 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 

Y es ThreadPoolExecutor que realmente define el método de 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()