Меня просто смутил какой-то код, который я написал. Я с удивлением обнаружил, что:
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(f, iterable))
и
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
results = list(map(lambda x: executor.submit(f, x), iterable))
дают разные результаты. Первый создает список любого типа f, второй создает список объектов concurrent.futures.Future, которые затем должны оцениваться с помощью метода result(), чтобы получить возвращаемое значение f.
Моя основная проблема заключается в том, что это означает, что executor.map не может использовать concurrent.futures.as_completed, что представляется чрезвычайно удобным способом оценки результатов некоторых длительных вызовов базы данных, которую я создаю как они становятся доступными.
Я не совсем понимаю, как работают объекты concurrent.futures.ThreadPoolExecutor - наивно, я бы предпочел (несколько более подробный):
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
result_futures = list(map(lambda x: executor.submit(f, x), iterable))
results = [f.result() for f in futures.as_completed(result_futures)]
более кратким executor.map, чтобы использовать возможное усиление производительности. Неужели я ошибаюсь?