corrutinas

Para crealas, async def. Para esperarlas, await. Cuando se crea, cuando se llama a una función definida con async def, obtenemos la corrutina, que no es más que un objeto con la definición del cómputo que queremos realizar, pero éste no se realiza. Para ejecutarlas, tenemos que llamarlas dentro del bucle de eventos de asyncio. El bucle se crea con asyncio.run(coroutine()), y para ejecutarlas dentro simplemente las llamamos con await. Tenemos tres formas de ejecutar corrutinas:

import asyncio

async def foo(param):
    ....
    return ...

asyncio.run(foo(param_value))

Si nos fijamos, las dos primeras no nos permite ejecutar código de forma concurrente, puesto que nos obligan a esperar al resultado de su ejecución. Incluso al ejecutar asyncio.run(...), nos quedaremos esperando hasta que ese bloque de código acabe antes de que se ejecute la siguiente línea, no se transfiere el control fuera de la ejecución del bucle de eventos cuando dentro de él se libera el GIL.