Меня просто смутил какой-то код, который я написал. Я с удивлением обнаружил, что:
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
, чтобы использовать возможное усиление производительности. Неужели я ошибаюсь?