Don't understand this asyncio error

Here's the code.

import asyncio
import aiohttp


async def fetch_numbers(session):
    counter = 0
    while True:
        counter += 1
        resp = await session.post("https://httpbin.org/post", json={"number": counter})
        yield await resp.json()


async def main():

    async with aiohttp.ClientSession() as session:
        counter = 0
        async for item in fetch_numbers(session):
            counter += 1
            print(item)
            if counter == 99:
                break

if __name__ == '__main__':
    asyncio.run(main())

Here's the error I get:

unhandled exception during asyncio.run() shutdown
task: <Task finished coro=<<async_generator_athrow without __name__>()> 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 feel like this error shouldn't happen? I'm not sending anything using the generator. I'm open to any suggestions!

Posted Apr 10, 2019, 1:27 PM UTC

57
lanemikmikelane•

From my reading here, it looks like the issue might be the fetch_numbers iterator. It looks like you might need to call next() on it or to call send(None) to it before you try to iterate over it.

1
doesntthinkmuchOP•

Calling send(None) is exactly equivalent to calling a generator's next() method

A iterating through something calls next() though, right?

1
lanemikmikelane•

Yeah. But if I'm reading that PEP right, this is a peculiarity of that particular kind of coroutine generator.

1
1114111yield from pedestrians•

I can't see anything that could cause that problem in your code, and it works fine for me on linux with Python 3.7.2 and the latest version of aiohttp.

1
1114111yield from pedestrians•

Actually I was playing around with it a little more and it seems like this happens if an asynchronous generator is deleted before it is finished iterating (like when you break out of the loop, and I didn't wait that long when I tested it earlier). I still don't know why it does this, but I think you can just ignore that error. Maybe someone with more experience with asyncio can provide more insight into why this happens.

1
1114111yield from pedestrians•

Ok, I took one last stab at this, and I think this is a problem with the new asyncio.run function. It works fine with

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
1
doesntthinkmuchOP•

Ah that's a good catch. Quite odd indeed. You think this might be a bug then?

1