Upd:
Starting with Python 3.6 we have asynchronous generators and able to use yield directly inside coroutines.
import asyncio async def async_generator(): for i in range(3): await asyncio.sleep(1) yield i*i async def main(): async for i in async_generator(): print(i) loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.run_until_complete(loop.shutdown_asyncgens()) # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens loop.close()
Old answer for Python 3.5:
You can't yield inside coroutines. Only way is to implement Asynchronous Iterator manually using __aiter__/__anext__ magic methods. In your case:
import asyncio class async_generator: def __init__(self, stop): self.i = 0 self.stop = stop async def __aiter__(self): return self async def __anext__(self): i = self.i self.i += 1 if self.i <= self.stop: await asyncio.sleep(1) return i * i else: raise StopAsyncIteration async def main(): async for i in async_generator(3): print(i) if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(main())
Output:
0 1 4
Here're two more examples: 1, 2
asyncon the other hand would suggest that the called function cannot depend on it state. Otherwise you will have data races. It seems really cumbersome to support async generators, they would need to be wrapped with locking mechanisms. So probably answer to your question is somewhere in this direction.