Interview question
What is the concurrent.futures module and how does it simplify thread/process pools? concurrent.futures module क्या है और thread/process pools को कैसे simplify करता है?
Answer
concurrent.futures provides a high-level interface (ThreadPoolExecutor and ProcessPoolExecutor) for running tasks concurrently, abstracting away manual thread/process creation and management.
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
import time
def fetch_url(url):
time.sleep(1) # simulating network delay
return f'Data from {url}'
urls = ['url1', 'url2', 'url3', 'url4']
# ThreadPoolExecutor - good for I/O-bound tasks
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(fetch_url, urls))
print(results) # all 4 urls fetched concurrently, ~1s total instead of 4s
# Using submit() for more control, and as_completed() for results as they finish
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(fetch_url, url): url for url in urls}
for future in as_completed(futures):
url = futures[future]
try:
result = future.result()
print(f'{url}: {result}')
except Exception as e:
print(f'{url} failed: {e}')
# ProcessPoolExecutor - same API, but for CPU-bound tasks (true parallelism)
def cpu_intensive(n):
return sum(i * i for i in range(n))
if __name__ == '__main__':
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(cpu_intensive, [10_000_000] * 4))
# Advantage over raw threading/multiprocessing: consistent, simple API
# (.submit, .map, .result) that works the same way for both thread
# and process pools - just swap the executor classconcurrent.futures ThreadPoolExecutor और ProcessPoolExecutor की high-level interface देता है, tasks को concurrently चलाने के लिए, manual thread/process creation को abstract करते हुए।
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
import time
def fetch_url(url):
time.sleep(1)
return f'Data from {url}'
urls = ['url1', 'url2', 'url3', 'url4']
# ThreadPoolExecutor - I/O-bound tasks के लिए अच्छा
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(fetch_url, urls))
print(results) # ~1s में सभी 4, 4s में नहीं
# submit() और as_completed() से ज़्यादा control
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(fetch_url, url): url for url in urls}
for future in as_completed(futures):
url = futures[future]
try:
result = future.result()
print(f'{url}: {result}')
except Exception as e:
print(f'{url} fail: {e}')
# ProcessPoolExecutor - CPU-bound tasks के लिए
def cpu_intensive(n):
return sum(i * i for i in range(n))
if __name__ == '__main__':
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(cpu_intensive, [10_000_000] * 4))Was this answer clear?