python-corrutinas

Qué son y cómo usar corrutinas en Python

Las corrutinas en Python son una forma de realizar tareas asincrónicas y concurrentes.

Una corrutina en Python es una función que puede pausarse y luego reanudarse, permitiendo que otras tareas se ejecuten en el ínterin.

Esta capacidad de suspensión y reanudación las hace adecuadas para tareas que implican concurrencia (como la programación asincrónica, la manipulación de flujos de datos y la creación de pipelines de procesamiento).

En cierta forma, la corrutinas son similares a los generadores, pero con capacidades adicionales. Mientras que los generadores producen una secuencia de valores, las corrutinas pueden consumir valores, producir valores y gestionar el flujo de control.

Definición de una corrutina

Las corrutinas se definen utilizando la palabra clave async def en lugar de def, y utilizan await para suspender la ejecución y esperar a que otra tarea se complete.

# Ejemplo básico de una corrutina
import asyncio

async def mi_corrutina():
    print("Comenzando la corrutina")
    await asyncio.sleep(1)
    print("Corrutina finalizada")

En este ejemplo, mi_corrutina es una función asincrónica que utiliza await para pausar su ejecución durante 1 segundo (simulando una tarea asíncrona como una espera de E/S o una solicitud de red).

Ejecución de corrutinas

El módulo asyncio de Python proporciona un marco para escribir código asincrónico utilizando corrutinas y realizar operaciones I/O eficientes.

Para ejecutar una corrutina, debemos añadirla al bucle de eventos de asyncio. La manera más sencilla de hacerlo es con asyncio.run().

import asyncio

async def saludar():
    print("Hola mundo")
    await asyncio.sleep(1)
    print("Desde LuisLlamas")

asyncio.run(saludar())

# salida:
# hola mundo
# ...(espera de un segundo)...
# Desde LuisLlamas

En este ejemplo, saludar es una corrutina que se ejecuta en el bucle de eventos de asyncio. La ejecución se pausa durante 1 segundo entre los dos print.

Esperar a múltiples corrutinas

Las corrutinas son especialmente útiles cuando se necesitan realizar múltiples operaciones asincrónicas. Esto se puede gestionar utilizando asyncio.gather().

import asyncio

async def tarea(numero):
    print(f"Comenzando tarea {numero}")
    await asyncio.sleep(1)
    print(f"Terminando tarea {numero}")

async def main():
    await asyncio.gather(tarea(1), tarea(2), tarea(3))

asyncio.run(main())

En este ejemplo, main espera a que se completen tres corrutinas tarea en paralelo.

Aplicaciones comunes de las corrutinas

Programación Asíncrona

Las corrutinas son esenciales para la programación asíncrona, permitiendo la realización de múltiples operaciones de I/O sin bloquear el flujo del programa.

import asyncio
import aiohttp

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    html = await fetch_url('http://www.google.com')
    print(html)

asyncio.run(main())

Pipelines de Procesamiento

Las corrutinas se pueden usar para construir pipelines de procesamiento que manipulan flujos de datos en tiempo real.

import asyncio

async def productor(queue):
    for i in range(5):
        await queue.put(i)
        await asyncio.sleep(1)

async def consumidor(queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"Consumiendo {item}")
        await asyncio.sleep(2)

async def main():
    queue = asyncio.Queue()
    await asyncio.gather(productor(queue), consumidor(queue))

asyncio.run(main())

En este ejemplo, el productor produce elementos y los coloca en una cola, mientras que el consumidor consume estos elementos, demostrando un pipeline simple.