python asynchronous python-3.5

python - ¿Cuál es la diferencia entre los decoradores @ types.coroutine y @ asyncio.coroutine?



asynchronous python-3.5 (2)

La diferencia es si tienes una declaración de rendimiento o no. Aquí está el código:

from types import coroutine as t_coroutine from asyncio import coroutine as a_coroutine, ensure_future, sleep, get_event_loop @a_coroutine def a_sleep(): print("doing something in async") yield 1 @t_coroutine def t_sleep(): print("doing something in types") yield 1 async def start(): sleep_a = a_sleep() sleep_t = t_sleep() print("Going down!") loop = get_event_loop() loop.run_until_complete(start())

En este ejemplo, todo parece igual: aquí está la información de depuración de pycharm (estamos parados en la línea "¡Bajando!"). Todavía no se imprime nada en la consola, por lo que las funciones aún no se han iniciado.

¡Pero si eliminamos el yield , la versión de types comenzará a funcionar instantáneamente!

from types import coroutine as t_coroutine from asyncio import coroutine as a_coroutine, ensure_future, sleep, get_event_loop @a_coroutine def a_sleep(): print("doing something in async") @t_coroutine def t_sleep(): print("doing something in types") async def start(): sleep_a = a_sleep() sleep_t = t_sleep() print("Going down!") loop = get_event_loop() loop.run_until_complete(start())

Ahora tenemos que doing something in types en consola impresa. Y aquí está la información de depuración:

Como puede ver , comienza justo después de la llamada , si no hay un resultado y devuelve Ninguno.

En cuanto al uso, debes usar siempre la versión asyncio . Si necesita ejecutarlo como disparar y olvidar (ejecutando instantáneamente y obteniendo resultados más adelante), use la función ensure_future .

Las documentaciones dicen:

@ asyncio.coroutine

Decorador para marcar corutines basados ​​en generadores. Esto permite que el generador use el rendimiento para llamar a las definiciones de sincronía, y también permite que el generador sea llamado por las definiciones de sincronía, por ejemplo, utilizando una expresión de espera.

_

@ types.coroutine (gen_func)

Esta función transforma una función de generador en una función de coroutine que devuelve un coroutine basado en generador. El coroutine basado en generador sigue siendo un iterador generador, pero también se considera que es un objeto coroutine y es esperable. Sin embargo, puede que no implemente necesariamente el __await__() .

Por lo tanto, parece que los propósitos son los mismos: marcar un generador como coroutine (lo que hace async def en Python3.5 y superior con algunas características).

Cuando necesito usar asyncio.coroutine cuando necesites usar types.coroutine , ¿cuál es la diferencia?


Otra diferencia sutil: las coroutinas basadas en generadores decoradas con @asyncio.coroutine probarán True para asyncio.iscoroutinefunction() , mientras que aquellas decoradas con @types.coroutine probarán False .

# testcoro.py import asyncio import inspect import types @asyncio.coroutine def old_coro_with_asyncio(): yield from asyncio.sleep(1) @types.coroutine def old_coro_with_types(): yield from asyncio.sleep(1) if __name__ == "__main__": for coro in (old_coro_with_asyncio, old_coro_with_types): print(coro.__name__, ''iscoroutine:'', asyncio.iscoroutine(coro)) print(coro.__name__, ''iscoroutinefunc:'', asyncio.iscoroutinefunction(coro))

Salida:

(py37) $ python3 testcoro.py old_coro_with_asyncio iscoroutine: False old_coro_with_asyncio iscoroutinefunc: True old_coro_with_types iscoroutine: False old_coro_with_types iscoroutinefunc: False

No obstante, ambos son aguardables.

* Tenga en cuenta también que esta diferencia no se aplica a sus _resultados: reemplace iscoroutinefunction() con iscoroutine() (que analiza un objeto de rutina), y old_coro_with_asyncio() + old_coro_with_types() evaluará False para ambos.