Skip to content

Instantly share code, notes, and snippets.

@kamal-github
Created July 31, 2026 06:04
Show Gist options
  • Select an option

  • Save kamal-github/30a4a2416e6ecff0207280cb2f8b2937 to your computer and use it in GitHub Desktop.

Select an option

Save kamal-github/30a4a2416e6ecff0207280cb2f8b2937 to your computer and use it in GitHub Desktop.
Demo of all the ways you can deal with futures.
from concurrent.futures import ALL_COMPLETED, FIRST_COMPLETED
from concurrent.futures import as_completed, wait
from concurrent.futures.thread import ThreadPoolExecutor
from concurrent.futures import Future
import time
products = [
{"id": 123, "category": "home appliance", "name": "microwave"},
{"id": 456, "category":"electronics", "name": "mobile"},
{"id": 22, "category": "home decor", "name": "bandharwal"},
{"id": 45, "category": "electronics", "name": "led tv"},
{"id": 444, "category": "electronics", "name": "camera"},
]
def get_products_by_category(category: str, max_results=10, timeout=2.0):
print(f"fetching products: category={category}, max_results={max_results}")
time.sleep(timeout)
prods = [p for p in products if p.get("category", "") == category.lower()]
# print(f"DONE fetching products: category={category}, max_results={max_results}\n")
return prods[:max_results]
def callbk(fut: Future):
print(f"callback got: {fut.result()}")
def callback_version():
with ThreadPoolExecutor(max_workers=3) as tpe:
f1 = tpe.submit(get_products_by_category, "electronics", 2)
f2 = tpe.submit(get_products_by_category, "home decor", 2)
f3 = tpe.submit(get_products_by_category, "home appliance", 2)
f1.add_done_callback(callbk)
f2.add_done_callback(callbk)
f3.add_done_callback(callbk)
print("main thread is still running, nothing blocked", "", "")
def as_completed_version():
with ThreadPoolExecutor(3) as tpe:
f1 = tpe.submit(get_products_by_category, "electronics", 2, 0.8)
f2 = tpe.submit(get_products_by_category, "home decor", 2, 3)
f3 = tpe.submit(get_products_by_category, "home appliance", 2, 0.2)
futures = (f1, f2, f3)
for f in as_completed(futures):
print(f"Got result: {f.result()}")
def wait_version():
with ThreadPoolExecutor(3) as tpe:
f1 = tpe.submit(get_products_by_category, "electronics", 2, 0.8)
f2 = tpe.submit(get_products_by_category, "home decor", 2, 3)
f3 = tpe.submit(get_products_by_category, "home appliance", 2, 0.2)
futures = (f1, f2, f3)
done_futures, not_done_futures = wait(futures, return_when=ALL_COMPLETED)
print("waiting for all to complete") # prints when all of them are done and proceed to read results.
for df in done_futures:
print(f"Got result: {df.result()}")
print(f"current status of futures after wait done={len(done_futures)}, not_done={len(not_done_futures)}")
def map_version():
with ThreadPoolExecutor(3) as tpe:
"""
this version uses map which returns result as and when completed, so looping over results
block till one of the results is ready or has exception. Comes out of order, very similar to
`as_completed(futures_iterable)` when work submitted by `ex.submit()`.
"""
results = tpe.map(get_products_by_category, ['electronics', 'home decor'], [2,2], [0.2, 3])
if __name__=="__main__":
# callback_version()
# as_completed_version()
wait_version()
# map_version()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment