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.
Ejemplos prácticos
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.