Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use 'yield' inside async function?

I want to use generator yield and async functions. I read this topic, and wrote next code:

import asyncio  async def createGenerator():     mylist = range(3)     for i in mylist:         await asyncio.sleep(1)         yield i*i  async def start():     mygenerator = await createGenerator()     for i in mygenerator:         print(i)  loop = asyncio.get_event_loop()  try:     loop.run_until_complete(start())  except KeyboardInterrupt:     loop.stop()     pass 

But i got the error:

SyntaxError: 'yield' inside async function

How to use yield generator in async function?

like image 825
Ильдар Avatar asked May 31 '16 15:05

Ильдар


People also ask

How do you use yield in async function?

To pause execution, you need the yield keyword. When you execute the function, it returns an iterator that you can control with the next() method: 1function* fetchMovies() { 2 const data = yield fetch(); 3} 4 5const iter = fetchData(); 6iter. next(); // run the generator function up to the `yield` keyword.

How do you use yield in async in Python?

The way you drive it is by using its __next__ interface (called by the python built-in function next() ). This advances the generator to the next yield statement and returns you the value of the expression to the right of yield . You can do that again and again until the generator function runs out.

How do you call a function inside an async function?

Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Does an async function need to return?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.


1 Answers

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

like image 161
Mikhail Gerasimov Avatar answered Sep 22 '22 12:09

Mikhail Gerasimov