expLog

Some AsyncIO terms

I often find myself confused by a few common terms used throughout asyncio, accidentally interchanging them with each other and then wondering why things are failing, or why they don't run.

The best way to deeply understand generators, coroutines, async generators and the rest in Python would be to understand them with context as they were introduced; the behavior makes sense when considered incrementally but not necessarily while looking backwards from where we are today.

Coroutine

  • async def, but no yield.
  • "Asynchronous data consumers"

Async Generator

  • async def and yield.
  • "Asynchronous data producers"

Generator

  • yield
  • "Data producers"

Function

  • The standard.

Generator based coroutines

An example

import asyncio

def function():
    print("this is a function")


async def coroutine():
    print("this is a coroutine")


def generator():
    print("generator step 1")
    yield 1

    print("generator step 2")
    yield 2


async def async_generator():
    print("async generator step 1")
    yield 1

    print("async generator step 2")
    yield 2


async def main():
    print(f"Call {function}")
    function()

    print(f"\nCall {coroutine}")
    await coroutine()

    print(f"\nCall {generator}")
    for x in generator():
        print(x)

    print(f"\nCall {async_generator}")
    async for x in async_generator():
        print(x)

asyncio.run(main())

Future

  • Represents the result of a computation
  • Can be awaited

Task

  • asyncio.task.Task: "A coroutine wrapped in a future"
  • A Task is a Future
  • Strictly tied to a given event loop.
  • Responsible for "kicking" a generator along 1 with steps

References:

Peps

1

I learned this from the AoSA book.

view source