Created
July 31, 2026 06:04
-
-
Save kamal-github/30a4a2416e6ecff0207280cb2f8b2937 to your computer and use it in GitHub Desktop.
Demo of all the ways you can deal with futures.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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