Skip to content

Not all generators containing await are compiled to async generators #114104

Closed
@mniip

Description

@mniip

Documentation

A generator of the form f(x) for x in await a first awaits a and then creates a regular sync generator, as can be seen in the following minimal reproducer:

import asyncio
async def foo():
    print("Entered foo")
    return [1, 2, 3]
async def main():
    gen = (x for x in await foo())
    print(gen)
    print(list(gen))
asyncio.run(main())
Entered foo
<generator object main.<locals>.<genexpr> at 0x7f8fce7f8110>
[1, 2, 3]

However the python language reference 6.2.8. Generator expressions states:

If a generator expression contains either async for clauses or await expressions it is called an asynchronous generator expression. An asynchronous generator expression returns a new asynchronous generator object, which is an asynchronous iterator (see Asynchronous Iterators).

This seems to suggest that the generator f(x) for x in await a does contain an await expression, so it should become an async_generator? However there is also:

However, the iterable expression in the leftmost for clause is immediately evaluated, so that an error produced by it will be emitted at the point where the generator expression is defined, rather than at the point where the first value is retrieved.

This seems to hint at an implementation detail that the leftmost for clause has special treatment and is always evaluated before the generator is constructed, but the interactions with await are unclear from this, especially whether this disqualifies the generator from becoming async.

I don't know whether this is an undocumented feature or a bug.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation in the Doc dir

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions