import concurrent.futures import itertools from typing import Callable, Iterable def execute_multithread(func: Callable, inputs: Iterable, n_workers): with concurrent.futures.ThreadPoolExecutor(max_workers=n_workers) as executor: futures = { executor.submit(func, **task) for task in itertools.islice(inputs, n_workers) } while futures: done, futures = concurrent.futures.wait( futures, return_when=concurrent.futures.FIRST_COMPLETED ) for future in done: yield future.result() for task in itertools.islice(inputs, len(done)): futures.add(executor.submit(func, **task))