executor.map()
, like the builtin map()
, only returns results in the order of the iterable, so unfortunately you can’t use it to determine the order of completion. concurrent.futures.as_completed()
is what you’re looking for – here’s an example:
import time
import concurrent.futures
times = [3, 1, 2]
def sleeper(secs):
time.sleep(secs)
print('I slept for {} seconds'.format(secs))
return secs
# returns in the order given
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
print(list(executor.map(sleeper, times)))
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [3, 1, 2]
# returns in the order completed
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
futs = [executor.submit(sleeper, secs) for secs in times]
print([fut.result() for fut in concurrent.futures.as_completed(futs)])
# I slept for 1 seconds
# I slept for 2 seconds
# I slept for 3 seconds
# [1, 2, 3]
Of course if you are required to use a map interface, you could create your own map_as_completed()
function which encapsulates the above (maybe add it to a subclassed Executor()
), but I think creating futures instances through executor.submit()
is a simpler/cleaner way to go (also allows you to provide no-args, kwargs).