Thread Pool with concurrent.futures
Why use ThreadPoolExecutor
Section titled “Why use ThreadPoolExecutor”Creating threads manually is okay for a few tasks.
For many tasks, prefer:
concurrent.futures.ThreadPoolExecutor
It provides:
- a thread pool
- easy result collection
- simpler error handling
Example: run many tasks
Section titled “Example: run many tasks”from concurrent.futures import ThreadPoolExecutor, as_completed
import time
def fetch(i: int) -> int:
time.sleep(0.2)
return i * i
results = []
with ThreadPoolExecutor(max_workers=5) as ex:
futures = [ex.submit(fetch, i) for i in range(10)]
for f in as_completed(futures):
results.append(f.result())
print(sorted(results))Exception handling
Section titled “Exception handling”If a worker raises an exception, future.result() raises it.
from concurrent.futures import ThreadPoolExecutor
def work(x: int) -> float:
return 10 / x
with ThreadPoolExecutor() as ex:
futures = [ex.submit(work, x) for x in [2, 1, 0]]
for f in futures:
try:
print(f.result())
except Exception as e:
print("Worker failed:", e)When to prefer a thread pool
Section titled “When to prefer a thread pool”- API calls
- scraping
- downloading files
- parallel file operations
🧪 Try It Yourself
Section titled “🧪 Try It Yourself”Exercise 1 – Submit a Task
Section titled “Exercise 1 – Submit a Task”Exercise 2 – Map Over a List
Section titled “Exercise 2 – Map Over a List”Exercise 3 – Check Future Done
Section titled “Exercise 3 – Check Future Done”pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading