PEP 492 introduced support for native coroutines and async / await syntax to Python 3.5. It is proposed here to extend Python's asynchronous capabilities by adding support for asynchronous generators.

Regular generators (introduced in PEP 255) enabled an elegant way of writing complex data producers and have them behave like an iterator.

However, currently there is no equivalent concept for the asynchronous iteration protocol ( async for ). This makes writing asynchronous data producers unnecessarily complex, as one must define a class that implements __aiter__ and __anext__ to be able to use it in an async for statement.

Essentially, the goals and rationale for PEP 255, applied to the asynchronous execution case, hold true for this proposal as well.

Performance is an additional point for this proposal: in our testing of the reference implementation, asynchronous generators are 2x faster than an equivalent implemented as an asynchronous iterator.

As an illustration of the code quality improvement, consider the following class that prints numbers with a given delay once iterated:

class Ticker: """Yield numbers from 0 to `to` every `delay` seconds.""" def __init__(self, delay, to): self.delay = delay self.i = 0 self.to = to def __aiter__(self): return self async def __anext__(self): i = self.i if i >= self.to: raise StopAsyncIteration self.i += 1 if i: await asyncio.sleep(self.delay) return i

The same can be implemented as a much simpler asynchronous generator:

async def ticker(delay, to): """Yield numbers from 0 to `to` every `delay` seconds.""" for i in range(to): yield i await asyncio.sleep(delay)