PY
Python Async Patterns

The Event Loop

Python execution is inherently single-threaded due to the Global Interpreter Lock (GIL). Traditional synchronous code blocks the entire thread while waiting for I/O operations (like network requests or database queries) to finish.

Asyncio bypasses this limitation by yielding control during waiting periods. The event loop acts as a sophisticated traffic controller, constantly pushing and pulling tasks on and off the active execution stack when they are blocked by external I/O.

The `await` keyword is the syntactic bridge that tells the event loop: "I am going to be waiting here for a bit, go do something else and come back to me when I am ready."

SnippetPython
import asyncio
import time

async def fetch_data(id):
    print(fclass="ttk-str">"Start fetching {id}...")
    await asyncio.sleep(2) # Simulates network I/O
    print(fclass="ttk-str">"Finished {id}!")
    return { class="ttk-str">"id": id, class="ttk-str">"data": class="ttk-str">"dummy" }

async def main():
    start = time.time()
    # Runs concurrently!
    results = await asyncio.gather(
        fetch_data(1),
        fetch_data(2),
        fetch_data(3)
    )
    print(fclass="ttk-str">"Took {time.time() - start:.2f}s") # Takes 2s, not 6s

asyncio.run(main())

Lesson Insights

Asyncio does not make CPU execution parallel, it makes I/O concurrent.

The event loop manages a single thread, switching tasks when they `await`.

`asyncio.gather` is a fast way to run multiple independent tasks simultaneously.

Related Knowledge