При указанных выше условиях в этом коде не будет условия гонки. В соответствии с документами concurrent.futures здесь происходит следующее:
- executor.submit (): возвращает объект Future, представляющий выполнение вызываемого объекта.
- as_completed (future_to_f_detail): возвращает итератор для экземпляров Future, предоставленных future_to_f_detail, который возвращает фьючерсы по мере их завершения (завершенные или отмененные фьючерсы).
Так что действительно для l oop потребляется итератор и возвращая одно за другим каждое будущее, которое является выходом, с помощью as_completed ()
Так что, если только call_back () или функция, которую мы вызвали, не представляют какую-то функциональность asyn c (как в примере, описанном @ dm03514 выше), мы просто работаем синхронно после for l oop
counter = 0
with ThreadPoolExecutor(max_workers=workers) as executor:
future_to_f_detail = {executor.submit(api_call, id): id for id in lst}
for future in as_completed(future_to_f_detail):
print(f"Entering the for loop for {counter+1} time")
counter +=1
try:
find_details = future.result()
except Exception as exc:
print(f"Finding {id} generated and exception: {exc}")
else:
f_det = callback_processing(find_details)
output.append(f_det)
return output
Если у нас есть массив 500 идентификаторов, и мы делаем 500 вызовов, и все вызовы дают будущее, мы напечатаем сообщение в печати 500 время, один раз перед входом в попытку l oop.
Мы не обязаны использовать Очередь, чтобы избежать условия гонки в этом случае. как таковые. Futures создает отложенное исполнение, когда мы используем submit, мы получаем будущее, которое будет использовано позже
Некоторые важные замечания и рекомендации:
- Ramalho, Luciano, Fluent Python, глава 17 Параллелизм с будущим.
- Бизли, Дэвид: Python Поваренная книга Глава 12 Параллелизм. Страница 516 Определение и задание актера