python yield python-3.5 python-asyncio

subplot python



¿Cómo usar ''rendimiento'' dentro de la función asíncrona? (3)

Quiero usar el rendimiento del generador y las funciones asíncronas. Leí este tema , y escribí el siguiente código:

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

Pero me salió el error:

SyntaxError: ''rendimiento'' dentro de la función asíncrona

¿Cómo utilizar el generador de rendimiento en función asíncrona?


El nuevo Python 3.6 viene con soporte para generadores asíncronos.

PEP 0525

Novedades en Python 3.6

PD: En el momento de escribir Python 3.6 sigue siendo beta. Si está en GNU / Linux u OS X y no puede esperar, puede probar Python nuevo con pyenv .


Esto debería funcionar con Python 3.6 (probado con 3.6.0b1):

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


Actualizaciones:

Comenzando con Python 3.6 tenemos generadores asíncronos y podemos usar el yield directamente dentro de las rutinas.

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.AbstractEventLoop.shutdown_asyncgens loop.close()

Antigua respuesta para Python 3.5:

No puedes yield dentro de los coroutines. La única manera es implementar el iterador asíncrono manualmente utilizando los métodos mágicos __aiter__ / __anext__ . En tu caso:

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())

Salida:

0 1 4

Aquí hay dos ejemplos más: 1 , 2