PEP 828 – Supporting 'yield from' in asynchronous generators – peps.python.org

rbanffy1 pts0 comments

PEP 828 – Supporting ‘yield from’ in asynchronous generators | peps.python.org

Following system colour scheme

Selected dark colour scheme

Selected light colour scheme

PEP 828 – Supporting ‘yield from’ in asynchronous generators

PEP 828 – Supporting ‘yield from’ in asynchronous generators

Author:<br>Peter Bierma<br>PEP-Delegate:<br>Yury Selivanov<br>Discussions-To:<br>Discourse thread<br>Status:<br>Accepted<br>Type:<br>Standards Track<br>Created:<br>07-Mar-2026<br>Python-Version:<br>3.16<br>Post-History:<br>07-Mar-2026,<br>09-Mar-2026<br>Resolution:<br>03-Aug-2026

Table of Contents<br>Abstract

Terminology

Motivation<br>Implementation complexity has gone down

Symmetry with synchronous generators

Subgenerator delegation is useful for asynchronous generators

Specification<br>Compiler changes

Changes to StopAsyncIteration

return statements inside asynchronous generators

yield from semantics in an asynchronous generator

Rationale<br>Relation to synchronous generators

Choice of yield from as the syntax

Backwards Compatibility

Security Implications

How to Teach This

Reference Implementation

Rejected Ideas<br>Using async yield from as the syntax<br>async from, await from, and similar spellings

Allowing delegation to synchronous subgenerators

Acknowledgements

Change History

Copyright

Abstract

This PEP introduces support for yield from in an<br>asynchronous generator function:

async def agenerator():<br>yield 1<br>yield 2<br>return 3

async def main():<br>result = yield from agenerator()<br>assert result == 3

Terminology

This PEP refers to an async def function that contains a yield<br>as an asynchronous generator, sometimes suffixed with “function”.<br>This is not to be confused with an asynchronous generator iterator,<br>which is the object returned by an asynchronous generator.

This PEP also uses the term “subgenerator” to refer to a generator, synchronous<br>or asynchronous, that is used inside a yield from.

Motivation

Implementation complexity has gone down

Historically, yield from was not added to asynchronous generators due to<br>concerns about the complexity of the implementation. To quote PEP 525:

While it is theoretically possible to implement yield from support for<br>asynchronous generators, it would require a serious redesign of the<br>generators implementation.

As of March 2026, the author of this proposal does not believe this to be true<br>given the current state of CPython’s asynchronous generator implementation.<br>This proposal comes with a reference implementation to argue this point, but<br>it is acknowledged that complexity is often subjective.

Symmetry with synchronous generators

yield from was added to synchronous generators in PEP 380 because<br>delegation to another generator is a useful thing to do. Due to the<br>aforementioned complexity in CPython’s generator implementation, PEP 525<br>omitted support for yield from in asynchronous generators, but this has<br>left a gap in the language.

This gap has not gone unnoticed by users. There have been three separate<br>requests for yield from or return behavior (which are closely related)<br>in asynchronous generators:

https://discuss.python.org/t/8897

https://discuss.python.org/t/47050

https://discuss.python.org/t/66886

Additionally, users have questioned<br>this design decision on Stack Overflow.

Subgenerator delegation is useful for asynchronous generators

The current workaround for the lack of yield from support in asynchronous<br>generators is to use a for/async for loop that manually yields each<br>item. This comes with a few drawbacks:

It obscures the intent of the code and increases the amount of effort<br>necessary to work with asynchronous generators, because each delegation<br>point becomes a loop. This damages the power of asynchronous generators.

asend(), athrow(), and aclose()<br>do not interact properly with the caller. This is the primary reason that<br>yield from was added in the first place.

Return values are not natively supported with asynchronous generators. The<br>workaround for this is to raise an exception, which increases boilerplate.

Specification

Compiler changes

The compiler will no longer emit a SyntaxError for<br>return or yield from statements inside asynchronous generators.

Changes to StopAsyncIteration

The StopAsyncIteration exception will gain a new value attribute<br>to be used as the result of yield from expressions in asynchronous generators.

This attribute can be supplied by passing a positional argument to<br>StopAsyncIteration. For example:

>>> exception = StopAsyncIteration(42)<br>>>> exception.value<br>42

If no argument is supplied, value will be None.

return statements inside asynchronous generators

In the body of an asynchronous generator function, the statement<br>return expression is roughly equivalent to<br>raise StopAsyncIteration(expression). However, similar to implicit<br>StopIteration exceptions raised inside synchronous generators,<br>the exception cannot be caught in the body of the asynchronous generator.

yield from semantics in an asynchronous generator

In an asynchronous generator, the statement

RESULT = yield...

asynchronous yield generators from generator implementation

Related Articles