Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen How the Event Loop Works | The Asyncio Foundation
Python Asyncio in Depth

How the Event Loop Works

Swipe um das Menü anzuzeigen

Everything in asyncio runs inside an event loop – a continuously running cycle that decides what runs next.

The Loop's Job

The event loop maintains a list of tasks. On each cycle, it:

  • Checks which tasks are ready to run;
  • Runs them until they hit an await;
  • Moves to the next ready task while the previous one waits.

No task ever truly runs in parallel. The loop gives each task a turn, switching between them at await points.

A Concrete Example

httpbin.org/delay/{n} is a public API that waits n seconds before responding – perfect for observing how the event loop handles slow operations.

12345678910111213141516171819202122232425262728293031
import asyncio import httpx import time import nest_asyncio nest_asyncio.apply() # Fetching from a slow endpoint to observe event loop scheduling async def fetch_slow(client, source, delay): print(f"Starting fetch from {source}") url = f"https://httpbin.org/delay/{delay}" response = await client.get(url) response.json() print(f"Done fetching from {source}") return f"Data from {source}" async def main(): start_time = time.time() async with httpx.AsyncClient() as client: # Running two slow requests concurrently results = await asyncio.gather( fetch_slow(client, "source_A", 2), fetch_slow(client, "source_B", 2), ) elapsed_time = time.time() - start_time print(results) print(f"Total time: {elapsed_time:.2f}s") # ~2s, not ~4s asyncio.run(main())

Both requests start almost simultaneously. The event loop starts fetch_slow(..., "source_A", 2), hits await response.json(), and immediately starts fetch_slow(..., "source_B", 2) instead of waiting. After ~2 seconds, both finish.

What await Actually Does

When a coroutine hits await, it suspends itself and hands control back to the event loop. The loop then picks the next ready task. When the awaited operation completes, the suspended coroutine is put back in the queue.

This is the core mechanism of asyncio:

  • await = "I'm waiting, someone else can run now";
  • Event loop = the scheduler that decides who runs next;
  • Coroutine = a function that knows how to pause and resume.

One Thread, Multiple Tasks

The event loop runs in a single thread. This means:

  • No race conditions from simultaneous memory access;
  • No need for locks when reading or writing shared data;
  • But also: a blocking call (like time.sleep()) freezes the entire loop.
12345678910111213141516171819202122232425262728
import asyncio import time import nest_asyncio nest_asyncio.apply() async def bad_example(): print("Starting bad...") time.sleep(1) # Blocking — freezing the entire event loop print("Done bad") async def good_example(): print("Starting good...") await asyncio.sleep(1) # Non-blocking — keeping the loop running print("Done good") async def main(): print("=== bad_example (blocks the loop) ===") start_time = time.time() await asyncio.gather(bad_example(), bad_example()) print(f"Total time: {time.time() - start_time:.2f}s\n") # ~2s print("=== good_example (non-blocking) ===") start_time = time.time() await asyncio.gather(good_example(), good_example()) print(f"Total time: {time.time() - start_time:.2f}s") # ~1s asyncio.run(main())

Always use asyncio.sleep() instead of time.sleep() inside async code. This pattern – using async-aware versions of blocking operations – runs throughout the entire asyncio ecosystem.

question mark

What happens when a coroutine hits an await expression?

Wählen Sie die richtige Antwort aus

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 1. Kapitel 3

Fragen Sie AI

expand

Fragen Sie AI

ChatGPT

Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen

Abschnitt 1. Kapitel 3
some-alt