Zalgorithm

A conceptual overview of asyncio

NOTE: this is not a tutorial. Check out the links in the References section.


EDIT: (Feb 4, 2026) I’ve learned something, but am going to try a more hands-on approach. See notes/ The Trio Python async concurrency library.

EDIT2: (Feb4, 2026) for where I’m at, the Trio tutorial feels like a better introduction to asynchronous programming.

More useful notes:


“Modern versions of Python have support for ‘asynchronous code’ using something called ‘coroutines’, with async and await syntax.”1

coroutines #

A coroutine object is what is returned by an async def function.

The terms “asynchronous function” (or “coroutine function”) and “coroutine object” are often conflated as coroutine. I find that a tad confusing. In this article, coroutine will exclusively mean “coroutine object” – the thing produced by executing a coroutine function.2

A coroutine can be paused and resumed at various points within the function’s body. The pausing and resuming are what allow for asynchronous behavior3

Regular functions versus asynchronous functions #

Calling an asynchronous function (“a coroutine function”) returns a coroutine object:

In [4]: def foo_regular():
   ...:     print("Calling the function invokes its code")
   ...:

In [5]: foo_regular()
Calling the function invokes its code

In [7]: async def foo_asynchronous():
   ...:     print("Calling this function returns a coroutine")
   ...:

In [8]: foo_asynchronous()
Out[8]: <coroutine object foo_asynchronous at 0x7f32d9f43d00>

The coroutine object has to be explicitly started. Creating the coroutine (e.g. calling foo_asynchronous()) does not start it.

Python coroutines and generators #

Coroutines and coroutine functions were built into the Python language on top of the scaffolding of generators.2

Like a coroutine, calling a generator function doesn’t run the function:

In [9]: def foo_bar_baz():
   ...:     yield "foo"
   ...:     yield "bar"
   ...:     yield "baz"
   ...:

In [10]: foo_bar_baz()
Out[10]: <generator object foo_bar_baz at 0x7f32db0401a0>

In [11]: fbb = foo_bar_baz()

In [13]: next(fbb)
Out[13]: 'foo'

In [14]: next(fbb)
Out[14]: 'bar'

In [15]: next(fbb)
Out[15]: 'baz'

In [16]: next(fbb)

Tasks #

Tasks are coroutines (not coroutine functions) that are tied to an event-loop.

The recommended way to create tasks is with asyncio.create_task() .

Creating a task adds a callback to run the task to the event loop’s collection of jobs.

Managing the event loop #

import asyncio


async def add_ab(a, b):
    print(f"a+b={a + b}")


async def main():
    asyncio.create_task(add_ab(2, 3))
    asyncio.create_task(add_ab(3, 4))


if __name__ == "__main__":
    asyncio.run(main())

# ❯ uv run main.py
# a+b=5
# a+b=7

Await #

await is a Python keyword that’s used either as:

await <coroutine>
await <task>

The behaviour of await depends on whether a coroutine or a task is being awaited. (This needs clarification.)

See: notes/ Running coroutines in Python

References #

docs.python.org (Python 3.14.3). “A Conceptual Overview of asyncio.” Last updated: Feb 03, 2026. https://docs.python.org/3/howto/a-conceptual-overview-of-asyncio.html .

docs.python.org (Python 3.14.3). “asyncio — Asynchronous I/O.” Last updated: Feb 03, 2026. https://docs.python.org/3/library/asyncio.html .

docs.python.org (Python 3.14.3). “Subprocesses.” Last updated: Feb 03, 2026. https://docs.python.org/3/library/asyncio-subprocess.html .

FastAPI documentation. “Concurrency and async / await.” Accessed on: Feb 03, 2026. https://fastapi.tiangolo.com/async/ .

anordin95. “a-conceptual-overview-of-asyncio.” Accessed on: Feb 03, 2026, https://github.com/anordin95/a-conceptual-overview-of-asyncio .


  1. FastAPI documentation, “Concurrency and async / await,” Accessed on: Feb 03, 2026, https://fastapi.tiangolo.com/async/↩︎

  2. anordin95, “a-conceptual-overview-of-asyncio,” Accessed on: Feb 03, 2026, https://github.com/anordin95/a-conceptual-overview-of-asyncio↩︎ ↩︎

  3. anordin95, “a-conceptual-overview-of-asyncio,” Accessed on: Feb 03, 2026, https://github.com/anordin95/a-conceptual-overview-of-asyncio↩︎