5.1 Event Loop
Ahora vamos a hablar brevemente sobre la segunda parte de la asincronía, que nos ha estado rondando por todas partes: el ciclo de eventos (Event Loop)
, las tareas (Task)
y Future
.
Imagina el Event Loop como un director de orquesta, las Task como los músicos, y Future como las partituras que los músicos deben tocar. El director (Event Loop) coordina el trabajo de los músicos (Task), que interpretan la música (operaciones asíncronas), leyendo las partituras (Future).
El ciclo de eventos (Event Loop)
es la base de la programación asíncrona en Python. Es responsable de ejecutar tareas asíncronas, gestionar eventos y procesar entrada-salida. El ciclo de eventos verifica continuamente la existencia de nuevos eventos o tareas y las inicia tan pronto como están listas.
Funciones principales
-
run_forever()
: Inicia el ciclo de eventos y continúa su ejecución hasta que se llama astop()
. -
run_until_complete(future)
: Inicia el ciclo de eventos y lo finaliza tras completar el objeto futuro o la coroutine especificada. stop()
: Detiene el ciclo de eventos.-
create_task(coroutine)
: Programa la ejecución de una coroutine como tarea.
Ejemplo de uso:
import asyncio
async def hello():
print("Hello, world!")
await asyncio.sleep(1)
print("Hello again!")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()
En este ejemplo, primero usamos el método
get_event_loop()
para obtener el objeto actual
EventLoop
de la biblioteca asyncio
.
Luego, añadimos la coroutine hello
a este EventLoop
y le pedimos que lo ejecute utilizando el método run_until_complete()
.
En el último paso, cerramos el EventLoop
usando el método close()
.
Al ejecutar este código, verás que primero se imprime "Hello, world!", luego el programa espera 1 segundo, y después de eso se imprime "Hello again!". Esto demuestra cómo el Event Loop gestiona la ejecución de una función asíncrona.
Estas acciones las estudiaremos más a fondo en la próxima lección.
5.2 Tasks
Las tareas (Tasks)
son envoltorios para coroutines, que permiten gestionar su ejecución y supervisar su estado. Las tareas permiten ejecutar coroutines en paralelo, gestionándolas a través del ciclo de eventos.
Creación y gestión de tareas
-
asyncio.create_task(coroutine)
: Crea una tarea para la ejecución de una coroutine. -
Task.result()
: Devuelve el resultado de una tarea completada o lanza una excepción si la tarea finalizó con un error. Task.cancel()
: Cancela la ejecución de la tarea.
Ejemplo de uso:
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello")
async def main():
task = asyncio.create_task(say_hello())
await task
asyncio.run(main())
En este ejemplo, envolvemos la coroutine say_hello()
con un objeto Task
.
También es un objeto asíncrono, por lo que para obtener su
resultado, necesitamos aplicarle el operador await
.
Al ejecutar este código, el programa espera 1 segundo y luego imprime "Hello". Esto muestra cómo Task gestiona la ejecución de una coroutine y cómo podemos esperar a su finalización con await.
Se hablará más en detalle sobre el trabajo con tareas Task
en la próxima lección.
5.3 Futures
Los objetos Future
representan el resultado de
una operación asíncrona que estará disponible en el futuro. Permiten
gestionar el estado de una operación asíncrona, estableciendo
el resultado o la excepción.
Métodos principales:
-
set_result(result)
: Establece el resultado para el objetoFuture
. -
set_exception(exception)
: Establece una excepción para el objetoFuture
. -
result()
: Devuelve el resultado del objetoFuture
o lanza una excepción si la operación finalizó con un error. -
exception()
: Devuelve la excepción, si fue establecida.
Ejemplo de uso:
import asyncio
async def set_future(fut, value):
await asyncio.sleep(1)
fut.set_result(value)
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
await set_future(fut, 'Hello, future!')
print(fut.result())
asyncio.run(main())
En este ejemplo, creamos un Future, establecemos su valor después de un segundo, y luego imprimimos el resultado. Verás que el programa espera un segundo antes de imprimir 'Hello, future!'. Esto demuestra cómo Future representa un resultado que estará disponible en el futuro.
A diferencia de un objeto Task
, un objeto Future
está vinculado a un
Event Loop
específico, y la función asíncrona ejecutada puede escribir en él
su resultado. Aunque por lo general funciona un poco diferente.
Más a menudo, los objetos Future
se usan en conjunto con tareas Task
, que proporcionan un control de más alto nivel sobre las operaciones asíncronas.
Ahora que te has familiarizado con Event Loop
, Task
y Future
,
los estudiaremos más detalladamente.
GO TO FULL VERSION