Python Coroutine Lifecycle — ELI5

Think of a coroutine like a library book request. You walk up to the desk, fill out a request slip, and hand it over. The librarian doesn’t run to the shelves immediately — your request just exists on paper.

That’s step one: creating a coroutine. When you write async def fetch_data() and call fetch_data(), you haven’t actually done anything yet. You just made a request slip.

Now the librarian (the event loop) picks up your slip and starts working on it. The coroutine is running. But partway through, it needs a book from the back room. Instead of standing there waiting, the coroutine says “I’ll pause here — come get me when the book arrives.” That’s the suspended state.

While your coroutine naps, the librarian helps other people. Then the book arrives! The librarian taps your coroutine on the shoulder: “Hey, your book is here.” The coroutine wakes up and picks up exactly where it left off.

Eventually, the coroutine finishes its work and hands back a result. It’s done — you can’t restart it or reuse it. It lived its life.

Here’s the full journey:

  1. Created — the function is called, but nothing runs yet
  2. Running — the event loop is actively executing it
  3. Suspended — it hit an await and is waiting for something
  4. Running again — the thing it waited for is done, back to work
  5. Completed — it returned a value (or raised an error)

One thing to remember: A coroutine is not a function that runs — it’s a function that can run, pause, and resume. It only comes alive when something (usually the event loop) drives it forward.

pythonconcurrencyasynciocoroutines

See Also

  • Python Actor Model Why treating each piece of your program like a person with their own mailbox makes concurrency way less scary.
  • Python Aiocache Caching aiocache remembers expensive answers so your async Python app doesn't waste time asking the same question twice.
  • Python Aiofiles Async Io aiofiles lets your async Python program read and write files without freezing — because normal file operations secretly block everything.
  • Python Aiohttp Understand Aiohttp through an everyday analogy so Python behavior feels intuitive, not random.
  • Python Anyio Portability AnyIO lets your async Python code work with any async library — write once, run on asyncio or Trio without changes.