Async Programming: asyncio, async/await
আধুনিক Python async — event loop ও cooperative concurrency
1. Why Async?
Most real-world programs spend more time waiting than computing — waiting for a web response, a database query, a file. asyncio lets you write cooperative code that, while one task waits, switches to another — all in a single thread with zero locks.
2. The Event Loop and Coroutines
The event loop is a scheduler that runs coroutines — special functions defined with
async def. A coroutine pauses at every await statement; the loop then runs another
coroutine until its awaited operation is ready.
async def দিয়ে ঘোষিত বিশেষ ফাংশন। প্রতিটি await-এ coroutine বিরতি নেয়, loop তখন অন্য একটি চালাতে শুরু করে।
await-এ সুইচ হতে পারে।
3. Your First Async Program
Always start an async program with asyncio.run(main()) — that single call creates the event loop.
asyncio.run(main()) দিয়ে শুরু করতে হবে — এই এক কল-ই event loop তৈরি করে।import asyncio
async def greet(name, delay):
await asyncio.sleep(delay)
print(f"Hello, {name}!")
async def main():
await asyncio.gather(
greet("Arif", 1),
greet("Nabila", 2),
greet("Rahim", 1),
)
asyncio.run(main())
4. gather vs TaskGroup
asyncio.gather runs coroutines concurrently and returns their results in order. Python 3.11+
introduced TaskGroup, which automatically cancels siblings when one task raises — the
preferred modern pattern.
asyncio.gather coroutine-গুলো একসাথে চালায় ও ফলাফল ফেরত দেয়। Python 3.11+ থেকে TaskGroup — এতে একটি task ব্যর্থ হলে অন্যগুলো স্বয়ংক্রিয়ভাবে cancel হয় — এটিই আধুনিক প্যাটার্ন।
import asyncio
async def work(i):
await asyncio.sleep(0.5)
return i * i
async def main():
async with asyncio.TaskGroup() as tg:
tasks = [tg.create_task(work(i)) for i in range(1, 6)]
print([t.result() for t in tasks])
asyncio.run(main())
5. Timeouts and Cancellation
asyncio.wait_for gives a coroutine a deadline; if exceeded it raises
TimeoutError and cleanly cancels the task.
asyncio.wait_for coroutine-কে একটি deadline দেয় — সময় পেরিয়ে গেলে TimeoutError raise করে এবং task clean ভাবে cancel হয়।
import asyncio
async def slow():
await asyncio.sleep(3)
return "done"
async def main():
try:
result = await asyncio.wait_for(slow(), timeout=1.0)
print(result)
except asyncio.TimeoutError:
print("timed out!")
asyncio.run(main())
6. Common Pitfalls
⚠️ Don't do this
- Calling blocking
time.sleepinside a coroutine - Using
requestsin async code (it is blocking) - CPU-heavy work without
run_in_executor - Forgetting to
awaita coroutine
✅ Do this instead
await asyncio.sleep(seconds)httpx.AsyncClientoraiohttpawait loop.run_in_executor(None, heavy_fn)- Always
await, or store in aTask
7. Vocabulary (শব্দভাণ্ডার)
| Term | Meaning | বাংলায় |
|---|---|---|
| Coroutine | Function defined with async def, can pause at await. | async def-এ সংজ্ঞায়িত ফাংশন, await-এ বিরতি নিতে পারে। |
| Event loop | Scheduler that runs and resumes coroutines. | Coroutine চালানো ও resume করার scheduler। |
| Task | A coroutine scheduled to run in the loop. | Loop-এ চালানোর জন্য scheduled coroutine। |
| Awaitable | Anything that can be used with await. | await-এর সাথে ব্যবহারযোগ্য। |
| gather | Run several coroutines concurrently. | একসাথে কয়েকটি coroutine চালানো। |
| TaskGroup | 3.11+ structured-concurrency context manager. | 3.11+ structured-concurrency context manager। |
8. Practice Problems
-
Write a coroutine that sleeps 1 second and returns the string
"ready"; run it withasyncio.run.একটি coroutine লিখুন যা ১ সেকেন্ড sleep করবে এবং"ready"return করবে;asyncio.run-এ চালান।✨ Show Answer (উত্তর দেখুন)
ans1.pyimport asyncio async def ready(): await asyncio.sleep(1) return "ready" print(asyncio.run(ready())) -
Run 5 coroutines concurrently with
asyncio.gather; each returns its index squared.৫টি coroutineasyncio.gather-এ একসাথে চালান; প্রতিটি তার index-এর square ফেরত দেবে।✨ Show Answer (উত্তর দেখুন)
ans2.pyimport asyncio async def sq(i): await asyncio.sleep(0.2) return i*i async def main(): print(await asyncio.gather(*[sq(i) for i in range(5)])) asyncio.run(main()) -
Wrap a slow coroutine with a 1-second timeout and handle
TimeoutError.ধীর coroutine-কে ১ সেকেন্ডের timeout দিন ওTimeoutErrorhandle করুন।✨ Show Answer (উত্তর দেখুন)
ans3.pyimport asyncio async def slow(): await asyncio.sleep(3) async def main(): try: await asyncio.wait_for(slow(), 1) except asyncio.TimeoutError: print("gave up") asyncio.run(main()) -
What does
awaitactually do? Explain in two sentences.awaitআসলে কী করে — দুই বাক্যে বলুন।✨ Show Answer (উত্তর দেখুন)
Answer:
awaitsuspends the current coroutine and hands control back to the event loop, which can schedule another coroutine in the meantime. When the awaited awaitable is ready, the loop resumes the coroutine with its result.awaitবর্তমান coroutine-কে বিরতি দিয়ে control event loop-কে ফিরিয়ে দেয়; loop তখন অন্য coroutine চালাতে পারে। awaitable প্রস্তুত হলে loop ফলাফল সহ coroutine-কে resume করে। -
Use a
TaskGroupto run 3 concurrent tasks and collect their results.একটিTaskGroupদিয়ে ৩টি task একসাথে চালিয়ে ফলাফল সংগ্রহ করুন।✨ Show Answer (উত্তর দেখুন)
ans5.pyimport asyncio async def w(x): await asyncio.sleep(0.2) return x * 10 async def main(): async with asyncio.TaskGroup() as tg: a = tg.create_task(w(1)) b = tg.create_task(w(2)) c = tg.create_task(w(3)) print(a.result(), b.result(), c.result()) asyncio.run(main())
Summary — Module 33
asyncio provides single-threaded cooperative concurrency through async def coroutines
and the await keyword. Use asyncio.run to start, gather or
TaskGroup to run many tasks, and wait_for for timeouts. Never block the loop with
time.sleep or blocking libraries.
asyncio single-thread-এ cooperative concurrency দেয় — async def ও await। asyncio.run দিয়ে শুরু, gather/TaskGroup দিয়ে অনেক task, wait_for দিয়ে timeout। Loop কখনো time.sleep বা blocking লাইব্রেরি দিয়ে আটকাবেন না।