Interview question
How do you handle exceptions in threads and async tasks? Threads और async tasks में exceptions कैसे handle करें?
Answer
Exceptions raised inside a thread's target function don't automatically propagate to the main thread - they're silently printed but don't crash the calling code. Async tasks behave differently and require explicit handling too.
import threading
def risky_task():
raise ValueError('Something went wrong')
t = threading.Thread(target=risky_task)
t.start()
t.join()
print('Main thread continues normally')
# The exception is printed to stderr by the threading module,
# but the main thread is NOT interrupted or notified automatically
# FIX: capture the exception yourself and store/communicate it
class ThreadWithException(threading.Thread):
def __init__(self, target):
super().__init__()
self.target = target
self.exception = None
def run(self):
try:
self.target()
except Exception as e:
self.exception = e # store it for the main thread to check
t = ThreadWithException(risky_task)
t.start()
t.join()
if t.exception:
print(f'Thread raised: {t.exception}')
# Using concurrent.futures - exceptions ARE captured and re-raised via .result()
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor() as executor:
future = executor.submit(risky_task)
try:
future.result() # re-raises the original exception HERE
except ValueError as e:
print(f'Caught: {e}')
# Asyncio - exceptions in a task propagate when you await it
import asyncio
async def risky_async():
raise ValueError('Async error')
async def main():
try:
await risky_async()
except ValueError as e:
print(f'Caught async: {e}')
asyncio.run(main())Thread की target function में raise हुई exceptions main thread तक automatically propagate नहीं होतीं - चुपचाप print हो जाती हैं पर calling code को crash नहीं करतीं।
import threading
def risky_task():
raise ValueError('कुछ गलत हुआ')
t = threading.Thread(target=risky_task)
t.start()
t.join()
print('Main thread सामान्य रूप से जारी')
# Exception stderr पर print होता है पर main thread notify नहीं होता
# FIX: exception खुद capture करना
class ThreadWithException(threading.Thread):
def __init__(self, target):
super().__init__()
self.target = target
self.exception = None
def run(self):
try:
self.target()
except Exception as e:
self.exception = e
t = ThreadWithException(risky_task)
t.start()
t.join()
if t.exception:
print(f'Thread ने raise किया: {t.exception}')
# concurrent.futures से exceptions .result() पर re-raise होती हैं
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor() as executor:
future = executor.submit(risky_task)
try:
future.result()
except ValueError as e:
print(f'Caught: {e}')
# Asyncio - task की exception await पर propagate होती है
import asyncio
async def risky_async():
raise ValueError('Async error')
async def main():
try:
await risky_async()
except ValueError as e:
print(f'Caught async: {e}')
asyncio.run(main())Was this answer clear?