CodeGym /Cursos /Python SELF ES /Bucle de Eventos

Bucle de Eventos

Python SELF ES
Nivel 25 , Lección 5
Disponible

6.1 Obteniendo el bucle de eventos

El Bucle de Eventos (Event Loop) es un componente central en la programación asíncrona usando el módulo asyncio en Python. Gestiona la ejecución de tareas asíncronas, el manejo de eventos y la ejecución de operaciones de entrada/salida. El bucle de eventos permite que múltiples tareas se ejecuten al mismo tiempo sin bloquear el hilo principal de ejecución.

Creación y obtención del bucle de eventos

  • asyncio.get_event_loop(): Devuelve el bucle de eventos actual o crea uno nuevo si no hay uno.
  • asyncio.new_event_loop(): Crea un nuevo bucle de eventos.
  • asyncio.set_event_loop(loop): Establece el bucle de eventos indicado como el actual.

Ejemplo:

asyncio tiene un bucle de eventos actual que contiene todas las tareas ejecutándose. Puedes obtener el bucle de eventos actual o crear uno nuevo y establecerlo como el actual. Esto es lo que pasa en el ejemplo de abajo.


import asyncio

loop = asyncio.get_event_loop()
print(loop)  # Bucle de eventos actual
new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)
print(asyncio.get_event_loop())  # Nuevo bucle de eventos establecido

Vale la pena notar que el método get_event_loop() devuelve el bucle de eventos activo actual. La creación de un nuevo bucle de eventos y su establecimiento debe hacerse con precaución para evitar conflictos en aplicaciones asíncronas.

Ejecutando el bucle de eventos

  • run_forever(): Ejecuta el bucle de eventos y continúa su ejecución hasta que se llama a stop().
  • run_until_complete(future): Ejecuta el bucle de eventos y lo detiene al finalizar la coroutine dada o el objeto futurible.

Ejemplo:

El bucle de eventos se puede ejecutar en dos modos: trabajar infinitamente — algo como un while True, o hasta que se complete una tarea específica.


import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)
    print("World")
            
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()

Si iniciaste el Event Loop en modo run_forever(), estará dando vueltas internamente infinitamente. El método run_forever() solo finalizará si alguna tarea asíncrona invoca el método stop() en nuestro EventLoop.

Detener el bucle de eventos

  • stop(): Detiene el bucle de eventos.
  • is_running(): Devuelve True si el bucle de eventos está en ejecución.

Ejemplo:

Si el bucle se ejecuta en modo infinito, está constantemente recibiendo tareas y ejecutándolas, no se detendrá por sí solo. Alguien debe obtener el objeto de nuestro bucle actual y llamar al método stop() en él. Para saber si el bucle infinito está activo o no, hay que llamar al método is_running().


import asyncio
            
loop = asyncio.get_event_loop()
loop.stop()
print(loop.is_running())  # False

6.2 Métodos importantes del bucle de eventos

Método call_soon(callback, *args)

Planifica la llamada de la función callback con argumentos *args lo más pronto posible.


import asyncio

def my_callback():
    print("Callback ejecutado")
            
loop = asyncio.get_event_loop()
loop.call_soon(my_callback)
loop.run_forever()

Coloca la función callback al inicio de la lista de tareas para que comience a ejecutarse lo más pronto posible. Puedes pasar funciones no asíncronas a este método. Este método es útil cuando necesitas realizar una tarea con el menor retraso posible, especialmente cuando se requiere una respuesta inmediata en una aplicación asíncrona.

Método call_later(delay, callback, *args)

Planifica la llamada de la función callback con argumentos *args después de delay segundos.


import asyncio

def my_callback():
    print("Callback ejecutado tras retraso")
            
loop = asyncio.get_event_loop()
loop.call_later(2, my_callback)
loop.run_forever()

Este método permite realizar una llamada diferida a una función: el primer argumento es el retraso en segundos (puede ser fraccionario), el siguiente es una referencia a la función y sus parámetros. Puedes pasar funciones no asíncronas a este método. Este método se puede usar para gestionar la ejecución de tareas con diferentes niveles de urgencia, lo que es útil al diseñar sistemas asíncronos complejos.

Método call_at(when, callback, *args)

Planifica la llamada de la función callback con argumentos *args en el momento when.


import asyncio
import time
            
def my_callback():
    print("Callback ejecutado en tiempo específico")
            
loop = asyncio.get_event_loop()
when = loop.time() + 2  # Dentro de 2 segundos desde el tiempo actual del bucle de eventos
loop.call_at(when, my_callback)
loop.run_forever()

Si quieres ejecutar una tarea no en 5 segundos, sino, por ejemplo, a las 15:00 o las 24:00, te será más conveniente usar la función call_at(), que funciona igual que la función call_soon(), pero como primer parámetro recibe no la duración de la pausa, sino el tiempo en el que se debe llamar a la función dada. Puedes pasar funciones no asíncronas a este método.

Ventajas y características

Ejecución asíncrona: El bucle de eventos permite ejecutar muchas tareas en paralelo sin bloquear el hilo principal de ejecución.

Gestión eficiente de recursos: Las operaciones de entrada/salida asíncronas se ejecutan sin bloqueo, lo que hace que los programas sean más eficientes.

Flexibilidad y escalabilidad: El bucle de eventos soporta muchos métodos para planificar tareas y manejar eventos, lo que permite crear aplicaciones asíncronas complejas y escalables.

6.3 Interacción con tareas y objetos futuros

El bucle de eventos gestiona la ejecución de tareas (Tasks) y objetos futuros (Futures). Monitorea su estado y asegura su ejecución a medida que están listos.

Ejemplo:


import asyncio

async def main():
    await asyncio.sleep(1)
    print("Tarea completada")
            
loop = asyncio.get_event_loop()
task = loop.create_task(main())
loop.run_until_complete(task)

En este ejemplo se muestra cómo el bucle de eventos gestiona la ejecución de una tarea creada con el método create_task. Los métodos call_soon(), call_later() y call_at() se pueden usar para gestionar la ejecución de tareas con diferentes niveles de urgencia, lo que es útil al diseñar sistemas asíncronos complejos.

1
Cuestionario/control
Multithreading, nivel 25, lección 5
No disponible
Multithreading
Multithreading
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION