⚡ Python Tutorial — Async Programming (async / await)

Introduction 🌟

Async programming allows Python to handle many tasks concurrently without blocking. It is ideal for I/O-bound operations such as:

  • 🌐 API calls
  • 📁 File operations
  • ⏳ Timers
  • 🔌 Network requests

Note

💡 Async ≠ Parallel — It's cooperative multitasking
💡 async/await introduced in Python 3.5
💡 Runs on the event loop

1. Key Concepts 🧠

  • Coroutine → an async function
  • Event loop → scheduler for async tasks
  • await → pauses coroutine until result is ready
  • Task → scheduled coroutine

2. Creating an Async Function 🔧

basic_async.py

import asyncio

async def greet():
    print("Hello async world!")

asyncio.run(greet())

async def defines a coroutine
✔ Must be executed using asyncio.run()

3. Using await ⏳

await_example.py

import asyncio

async def task():
    print("Start...")
    await asyncio.sleep(2)
    print("End after 2 seconds!")

asyncio.run(task())

await suspends execution but does NOT block the program

4. Running Multiple Coroutines Concurrently ⚡

async_gather.py

import asyncio

async def work(n):
    print(f"Task {n} started")
    await asyncio.sleep(1)
    print(f"Task {n} finished")

async def main():
    await asyncio.gather(
        work(1),
        work(2),
        work(3),
    )

asyncio.run(main())

✔ All tasks run concurrently under the event loop

5. Creating Tasks (Recommended for Background Work) 🎯

create_task.py

import asyncio

async def download(n):
    print(f"Downloading {n}...")
    await asyncio.sleep(2)
    print(f"Done {n}")

async def main():
    task1 = asyncio.create_task(download("File1"))
    task2 = asyncio.create_task(download("File2"))

    print("Tasks started...")
    await task1
    await task2

asyncio.run(main())

create_task() schedules functions immediately

6. Async with Timeout ⏱️

timeout_example.py

import asyncio

async def slow():
    await asyncio.sleep(5)

async def main():
    try:
        await asyncio.wait_for(slow(), timeout=2)
    except asyncio.TimeoutError:
        print("Timeout!")

asyncio.run(main())

7. Async Context Managers & Async Iterators 🔄

Async Context Manager

async_context_manager.py

class AsyncManager:
    async def __aenter__(self):
        print("Enter")
        return self

    async def __aexit__(self, exc_type, exc, tb):
        print("Exit")

async def main():
    async with AsyncManager():
        print("Inside async context")

asyncio.run(main())

Async Iterator

async_iter.py

class Counter:
    def __init__(self):
        self.x = 0

    async def __anext__(self):
        if self.x >= 3:
            raise StopAsyncIteration
        await asyncio.sleep(1)
        self.x += 1
        return self.x

    def __aiter__(self):
        return self

async def main():
    async for n in Counter():
        print(n)

asyncio.run(main())

8. Real-World Example — Fetching URLs Concurrently 🌐

http_example.py

import asyncio
import aiohttp

async def fetch(url, session):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    urls = ["https://example.com", "https://google.com"]

    async with aiohttp.ClientSession() as session:
        results = await asyncio.gather(
            *[fetch(url, session) for url in urls]
        )
        print(results)

asyncio.run(main())

✔ Perfect use case for async programming

9. asyncio.sleep() vs time.sleep() 💤

FunctionBlocks?Used In
time.sleep()YesThreads
asyncio.sleep()NoAsync coroutines

10. Handling Exceptions in Async Tasks ⚠️

async_exception.py

async def faulty():
    raise ValueError("Oops!")

async def main():
    try:
        await faulty()
    except Exception as e:
        print("Caught:", e)

asyncio.run(main())

11. Compare: Async vs Threading vs Multiprocessing ⚔️

FeatureAsyncThreadingMultiprocessing
Best forI/O tasksI/O tasksCPU-heavy tasks
Parallel?NoNo (GIL)Yes
Memory UsageLowMediumHigh

12. Best Practices 💡

  • ✔ Always use asyncio.run() to start async code
  • ✔ Never use time.sleep() inside async functions
  • ✔ Use gather() or create_task() for concurrency
  • ✔ Use await only inside async functions
  • ✔ Prefer aiohttp, aiomysql, aioredis for async I/O

Conclusion 🎉

>>“Async programming enables Python to handle thousands of I/O operations efficiently — without blocking.” ✨

You now fully understand Async Programming (async/await) in Python! Want the next topic? Try AsyncIO Tasks, Event Loop Internals, aiohttp, FastAPI Async, or WebSockets. Just tell me! 😊