¿Qué hace async / await?

Estoy tratando de envolver mi cabeza alrededor de async / await en python.

¿Estoy en el camino correcto?

( @coroutine = @types.coroutine )

@coroutine funciones async y @coroutine devuelven coroutine / generator, no el valor devuelto

Para ser técnicos, types.coroutine devuelve una coroutina basada en un generador que es diferente de los generadores y diferente de las coroutinas.

await extrae el valor de retorno real de coroutine / generator.

await , similar al yield from , suspende la ejecución de la coroutine hasta que la espera finaliza y devuelve el resultado.

El resultado de la función asíncrona (coroutines) está destinado a agregarse al bucle de eventos.

Sí.

await crea un “puente” entre el bucle de eventos y la correlación esperada (habilitando el siguiente punto).

await crea un punto de suspensión que indica al ciclo de eventos que se realizará alguna operación de E / S, lo que le permitirá cambiar a otra tarea.

El rendimiento de @coroutine se comunica directamente con el ciclo de eventos. (saltando el llamante directo que espera el resultado)

No, los coroutines basados ​​en generadores utilizan el yield from una manera similar para await , no el yield .

await solo se puede utilizar dentro de funciones asíncronas.

Sí.

El rendimiento solo se puede utilizar en el interior de coroutine.

yield from se puede usar dentro de coroutines basados ​​en generadores (generadores decorados con types.coroutine ) y, desde Python 3.6, en funciones async que dan como resultado un generador asíncrono.

Código de demostración:

(ilustra todo el flujo de control entre async y types.coroutine y evento loop)

 import types class EL: """Fake An event loop.""" def __init__(self, outer_async): self.outer_async = outer_async def loop(self): print(' EL.loop : outer_async.send(None)') send_result = self.outer_async.send(None) # seed outer_async. print(' EL.loop : outer_async.send(None) -> outer_async_send_result = {}'.format(send_result)) do_loop = True loop_counter = 0 while do_loop: print() loop_counter += 1 try: arg = send_result + '-loop(send-{})'.format(loop_counter) print(' EL.loop.while : task.outer_async.send({})'.format(arg)) send_result = self.outer_async.send(arg) # raises StopIteration. print(' EL.loop.while : task.outer_async.send({}) -> send_result = {}'.format(arg, send_result)) except StopIteration as e: print(' EL.loop.while : except StopIteration -> {}'.format(e.value)) do_loop = False return loop_counter async def outer_async(label): inner_coro_arg = label + '-A1' print(' outer_async({}) : await inner_coro({})'.format(label, inner_coro_arg)) await_result = await inner_coro(inner_coro_arg) print(' outer_async({}) : await inner_coro({}) -> await_result = {}'.format(label, inner_coro_arg, await_result)) inner_coro_arg = label + '-A2' print(' outer_async({}) : await inner_coro({})'.format(label, inner_coro_arg)) await_result = await inner_coro(inner_coro_arg) print(' outer_async({}) : await inner_coro({}) -> await_result = {}'.format(label, inner_coro_arg, await_result)) return 555555 @types.coroutine def inner_coro(inner_coro_label): yld_arg = inner_coro_label + '-C(yield)' print(' inner_coro({}) : yield({})'.format(inner_coro_label, yld_arg)) yield_result = yield yld_arg print(' inner_coro({}) : yield({}) -> yield_result = {}'.format(inner_coro_label, yld_arg, yield_result)) return_value = yield_result + '-C(return)' print(' inner_coro({}) : return -> {}'.format(inner_coro_label, return_value)) return return_value def main(): loop = EL(outer_async('$$')) print('main() : loop.loop') loop_outer_async = loop.loop() print('main() : loop.loop -> {}'.format(loop_outer_async)) if __name__ == '__main__': main() 

Resultado:

 main() : loop.loop EL.loop : outer_async.send(None) outer_async($$) : await inner_coro($$-A1) inner_coro($$-A1) : yield($$-A1-C(yield)) EL.loop : outer_async.send(None) -> outer_async_send_result = $$-A1-C(yield) EL.loop.while : task.outer_async.send($$-A1-C(yield)-loop(send-1)) inner_coro($$-A1) : yield($$-A1-C(yield)) -> yield_result = $$-A1-C(yield)-loop(send-1) inner_coro($$-A1) : return -> $$-A1-C(yield)-loop(send-1)-C(return) outer_async($$) : await inner_coro($$-A1) -> await_result = $$-A1-C(yield)-loop(send-1)-C(return) outer_async($$) : await inner_coro($$-A2) inner_coro($$-A2) : yield($$-A2-C(yield)) EL.loop.while : task.outer_async.send($$-A1-C(yield)-loop(send-1)) -> send_result = $$-A2-C(yield) EL.loop.while : task.outer_async.send($$-A2-C(yield)-loop(send-2)) inner_coro($$-A2) : yield($$-A2-C(yield)) -> yield_result = $$-A2-C(yield)-loop(send-2) inner_coro($$-A2) : return -> $$-A2-C(yield)-loop(send-2)-C(return) outer_async($$) : await inner_coro($$-A2) -> await_result = $$-A2-C(yield)-loop(send-2)-C(return) EL.loop.while : except StopIteration -> 555555 main() : loop.loop -> 2