My First Python3 Bug – Breaking Asynchronous Generators

Recently I filed my first bug report for CPython, which turned out to be a release blocker! Here is the code snippet to produce this issue for <=3.7.4.

import asyncio

class TestAsyncGenerator:
    def __init__(self):
        pass

    async def aiter(self):
        yield 1
        yield 2

async def main():
    gen = TestAsyncGenerator()
    async for number in gen.aiter():
        break

asyncio.run(main())

# unhandled exception during asyncio.run() shutdown
# task: <Task finished coro=<()> exception=RuntimeError("can't send non-None value to a just-started coroutine")>
# RuntimeError: can't send non-None value to a just-started coroutine

I’m not too familiar with CPython internals, but looking at the patch it seems that immediately exiting the async for loop without letting the asynchronous iterator “checkpoint” has the effect of triggering a mistaken check thinking that a “just-started coroutine” is not an initialised coroutine.

This bug fix is coming soon to a CPython distribution near you, along with some resemblance of my test code 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s