En Python, la palabra clave await se utiliza para pausar la ejecución de una función asíncrona hasta que una tarea asíncrona se complete.

Esta palabra clave es una parte fundamental del manejo de la programación asíncrona en Python, permitiendo que tu código espere de manera eficiente a que se resuelvan las operaciones sin bloquear el hilo de ejecución.

Sintaxis

La sintaxis básica para usar await es la siguiente:

result = await some_awaitable()

Aquí, some_awaitable() es la llamada a una función async que produce un objeto awaitable (una corrutina), y await se utiliza para esperar a que se complete antes de continuar con el código.

Ejemplos prácticos

A continuación tienes algunos ejemplos de cómo se usa await en Python:

import asyncio

async def main():
    print("Inicio")
    await asyncio.sleep(1) # Simula una operación asíncrona
    print("Fin")

# Ejecutar la función asíncrona
asyncio.run(main())

En este ejemplo, await asyncio.sleep(1) pausa la ejecución de la función main durante un segundo sin bloquear el hilo de ejecución principal. Después de un segundo, el programa continúa y ejecuta print("Fin").

El siguiente ejemplo muestra cómo usar await para esperar los resultados de múltiples solicitudes de red concurrentes. Para ello, usarás la biblioteca aiohttp junto con la API pública JSONPlaceholder.

Antes de ejecutar el ejemplo, instala aiohttp en tu entorno virtual con el siguiente comando:

$ pip install aiohttp

Una vez instalada la biblioteca, crea un archivo con el siguiente código:

# fetch_todos.py

import asyncio
import aiohttp

async def fetch_data(session, url):
    async with session.get(url) as response:
        return await response.json()

async def main():
    base = "https://jsonplaceholder.typicode.com"

    async with aiohttp.ClientSession() as session:
        user_ids = [1, 2, 3]

        users = await asyncio.gather(
            *(
                fetch_data(session, f"{base}/users/{uid}")
                for uid in user_ids
            )
        )
        todos = await asyncio.gather(
            *(
                fetch_data(session, f"{base}/todos?userId={uid}")
                for uid in user_ids
            )
        )
        for user, user_todos in zip(users, todos):
            pending = [t for t in user_todos if not t["completed"]]
            print(f"{user['name']}: {len(pending)} tareas pendientes")

asyncio.run(main())

Si ejecutas este script, obtendrás una salida similar a la siguiente:

Leanne Graham: 9 tareas pendientes
Ervin Howell: 12 tareas pendientes
Clementine Bauch: 10 tareas pendientes

En este ejemplo, la función fetch_data() usa await para esperar la respuesta de la API en formato JSON. En main(), las llamadas a await asyncio.gather() permiten lanzar todas las solicitudes de forma concurrente, de modo que mientras una espera su respuesta, las demás pueden avanzar sin bloquear el hilo de ejecución.

Uso de await

Los casos de uso más comunes de la palabra clave await incluyen los siguientes:

  • Esperar a que se completen las operaciones de entrada/salida (I/O) asíncronas, como solicitudes de red o acceso a bases de datos.
  • Coordinar tareas asíncronas que dependen del resultado de otras tareas.
  • Mejorar la eficiencia de las aplicaciones al permitir que se realicen otras operaciones mientras se espera la finalización de tareas asíncronas.

Resumiendo

La palabra clave await es esencial en Python para trabajar con programación asíncrona, permitiendo que las funciones esperen de manera eficiente a que se completen las tareas.

Conocer y utilizar await te permite escribir código que es más eficiente en el manejo de operaciones de entrada/salida y en la gestión de tareas que pueden ejecutarse de forma concurrente.