# Bucle de eventos

Código fuente: Lib/asyncio/events.py, Lib/asyncio/base_events.py

Prólogo

El bucle de eventos es el núcleo de cada aplicación asyncio. Los bucles de eventos ejecutan tareas asíncronas y llamadas de retorno, realizan operaciones de E/S de red y ejecutan subprocesos.

Los desarrolladores de aplicaciones normalmente deberían usar las funciones asyncio de alto nivel, como: `asyncio.run()`, y rara vez deberían necesitar hacer referencia al objeto de bucle o llamar a sus métodos. Esta sección esta dirigida principalmente a autores de código de nivel inferior, bibliotecas y frameworks, quienes necesitan un control mas preciso sobre el comportamiento del bucle de eventos.

Obtención del bucle de eventos

Las siguientes funciones de bajo nivel se pueden utilizar para obtener, establecer o crear un bucle de eventos:

`asyncio.``get_running_loop`()

  Retorna el bucle de eventos en ejecución en el hilo del sistema operativo actual.

  Si no hay un bucle de eventos en ejecución, se levanta un `RuntimeError`. Esta función únicamente puede ser llamada desde una corrutina o una llamada de retorno.

  Nuevo en la versión 3.7.

`asyncio.``get_event_loop`()

  Obtiene bucle de eventos actual.

  Si no hay un bucle de eventos actual establecido en el hilo actual del sistema operativo, el hilo del sistema operativo es el principal, y `set_event_loop()` aún no ha sido llamado, asyncio creará un nuevo bucle de eventos y lo establecerá como el actual.

  Dado que esta función tiene un comportamiento bastante complejo (especialmente cuando están en uso las políticas de bucle de eventos personalizadas), usar la función `get_running_loop()` es preferible antes que `get_event_loop()` en corrutinas y llamadas de retorno.

  Considere también usar la función `asyncio.run()` en lugar de usar funciones de bajo nivel para crear y cerrar manualmente un bucle de eventos.

`asyncio.``set_event_loop`(loop)

  Establece loop como el bucle de eventos actual para el hilo actual del sistema operativo.

`asyncio.``new_event_loop`()

  Crea un nuevo objeto de bucle de eventos.

Tenga en cuenta que el comportamiento de las funciones `get_event_loop()`, `set_event_loop()`, y `new_event_loop()` puede ser modificado mediante estableciendo una política de bucle de eventos personalizada.

Contenidos

Esta página de documentación contiene las siguientes secciones:

- La sección Métodos del bucle de eventos es la documentación de referencia de las APIs del bucle de eventos;

- La sección Callback Handles documenta las instancias `Handle` y `TimerHandle` las cuales son retornadas por métodos planificados como `loop.call_soon()` y `loop.call_later()`;

- La sección Objetos del servidor documenta tipos retornados por los métodos del bucle de eventos como `loop.create_server()`;

- La sección Implementaciones de bucle de eventos documenta las clases `SelectorEventLoop` y `ProactorEventLoop`;

- La sección Ejemplos muestra como trabajar con algunas APIs de bucle de eventos.

## Métodos del bucle de eventos

Los bucles de eventos tienen APIs de bajo nivel para lo siguiente:

- Iniciar y para el bucle

- Programación de llamadas de retorno

- Planificando llamadas retardadas

- Creando Futuros y Tareas

- Abriendo conexiones de red

- Creando servidores de red

- Transfiriendo archivos

- Actualización de TLS

- Viendo descriptores de archivos

- Trabajar con objetos sockets directamente

- DNS

- Trabajando con tuberías

- Señales Unix

- Ejecutando código en un hilos o grupos de procesos

- API para manejo de errores

- Habilitando el modo depuración

- Ejecutando Subprocesos

### Iniciar y para el bucle

`loop.``run_until_complete`(future)

  Se ejecuta hasta que future (una instancia de `Future`) se haya completado.

  Si el argumento es un objeto corrutina está implícitamente planificado para ejecutarse como una `asyncio.Task`.

  Retorna el resultado del Futuro o genera una excepción.

`loop.``run_forever`()

  Ejecuta el bucle de eventos hasta que `stop()` es llamado.

  Si `stop()` es llamado antes que `run_forever()`, el bucle va a sondear el selector de E/S una sola vez con un plazo de ejecución de cero, ejecuta todas las llamadas planificadas como respuesta a eventos E/S (y aquellas que ya hayan sido planificados), y entonces termina.

  Si `stop()` es llamado mientras `run_forever()` se está ejecutando, el loop ejecutará el lote actual de llamadas y después finalizará. Tenga en cuenta que llamadas planificadas por otras llamadas no se ejecutarán en este caso; en su lugar, ellas correrán la próxima vez que `run_forever()` o `run_until_complete()` sean llamados.

`loop.``stop`()

  Detener el bucle de eventos.

`loop.``is_running`()

  Retorna `True` si el bucle de eventos esta en ejecución actualmente.

`loop.``is_closed`()

  Retorna `True` si el bucle de eventos se cerró.

`loop.``close`()

  Cierra el bucle de eventos.

  El bucle no debe estar en ejecución cuando se llama a esta función. Cualquier llamada de retorno pendiente será descartada.

  Este método limpia todas las colas y apaga el ejecutor, pero no espera a que el ejecutor termine.

  Este método es idempotente e irreversible. No se debe llamar ningún otro método después que el bucle de eventos es cerrado.

coroutine `loop.``shutdown_asyncgens`()

  Programa todos los objetos asynchronous generator abiertos actualmente para cerrarlos con una llamada `aclose()`. Después de llamar este método, el bucle de eventos emitirá una advertencia si un nuevo generador asíncrono es iterado. Esto debe ser usado para finalizar de manera confiable todos los generadores asíncronos planificados.

  Tenga en cuenta que no hay necesidad de llamar esta función cuando `asyncio.run()` es utilizado.

  Ejemplo:

      try:
          loop.run_forever()
      finally:
          loop.run_until_complete(loop.shutdown_asyncgens())
          loop.close()

  Nuevo en la versión 3.6.

### Programación de llamadas de retorno

`loop.``call_soon`(callback, *args, context=None)

  Schedule the callback callback to be called with args arguments at the next iteration of the event loop.

  Llamadas que son ejecutadas en el orden en el que fueron registradas. Cada llamada será ejecutada exactamente una sola vez.

  Un argumento context opcional y solo de palabra clave que permite especificar una clase `contextvars.Context` personalizada en la cual callback será ejecutada. Cuando no se provee context el contexto actual es utilizado.

  Una instancia de `asyncio.Handle` es retornada, que puede ser utilizada después para cancelar la llamada.

  Este método no es seguro para subprocesos.

`loop.``call_soon_threadsafe`(callback, *args, context=None)

  Una variante de `call_soon()` que es segura para subprocesos. Debe ser usada en llamadas planificadas desde otro hilo.

  Vea sección concurrencia y multiproceso de la documentación.

Distinto en la versión 3.7: Fue agregado el parámetro solo de palabra clave context. Vea PEP 567 para mas detalles.

Nota

La mayoría de las funciones planificadas de `asyncio` no permiten pasar argumentos de palabra clave. Para hacer eso utilice `functools.partial()`:

    # will schedule "print("Hello", flush=True)"
    loop.call_soon(
        functools.partial(print, "Hello", flush=True))

El uso de objetos parciales es usualmente mas conveniente que utilizar lambdas, ya que asyncio puede renderizar mejor objetos parciales en mensajes de depuración y error.

### Planificando llamadas retardadas

El bucle de eventos provee mecanismos para planificar funciones de llamadas que serán ejecutadas en algún punto en el futuro. El bucle de eventos usa relojes monotónicos para seguir el tiempo.

`loop.``call_later`(delay, callback, *args, context=None)

  Planifica callback para ser ejecutada luego de delay número de segundos (puede ser tanto un entero como un flotante).

  Una instancia de `asyncio.TimerHandle` es retornada, la que puede ser utilizada para cancelar la ejecución.

  callback será ejecutada exactamente una sola vez. Si dos llamadas son planificadas para el mismo momento exacto, el orden en el que son ejecutadas es indefinido.

  El argumento posicional opcional args será pasado a la llamada cuando esta sea ejecutada. Si quieres que la llamada sea ejecutada con argumentos de palabra clave usa `functools.partial()`.

  Un argumento context opcional y solo de palabra clave que permite especificar una clase `contextvars.Context` personalizada en la cual callback será ejecutada. Cuando no se provee context el contexto actual es utilizado.

  Distinto en la versión 3.7: Fue agregado el parámetro solo de palabra clave context. Vea PEP 567 para mas detalles.

  Distinto en la versión 3.8: En Python 3.7 y versiones anteriores con la implementación del bucle de eventos predeterminada, el delay no puede exceder un día. Esto fue arreglado en Python 3.8.

`loop.``call_at`(when, callback, *args, context=None)

  Planifica callback para ser ejecutada en una marca de tiempo absoluta when (un entero o un flotante), usando la misma referencia de tiempo que `loop.time()`.

  El comportamiento de este método es el mismo que `call_later()`.

  Una instancia de `asyncio.TimerHandle` es retornada, la que puede ser utilizada para cancelar la ejecución.

  Distinto en la versión 3.7: Fue agregado el parámetro solo de palabra clave context. Vea PEP 567 para mas detalles.

  Distinto en la versión 3.8: En Python 3.7 y versiones anteriores con la implementación del bucle de eventos predeterminada, la diferencia entre when y el tiempo actual no puede exceder un día. Esto fue arreglado en Python 3.8.

`loop.``time`()

  Retorna el tiempo actual, como un `float`, de acuerdo al reloj monotónico interno del bucle de evento.

Nota

Distinto en la versión 3.8: En Python 3.7 y versiones anteriores los tiempos de espera (delay relativo o when absoluto) no deben exceder un día. Esto fue arreglado en Python 3.8.

Ver también

La función `asyncio.sleep()`.

### Creando Futuros y Tareas

`loop.``create_future`()

  Crea un objeto `asyncio.Future` adjunto al bucle de eventos.

  Esta es la manera preferida de crear Futures en asyncio. Esto permite que bucles de eventos de terceros provean implementaciones alternativas del objeto Future (con mejor rendimiento o instrumentación).

  Nuevo en la versión 3.5.2.

`loop.``create_task`(coro, *, name=None)

  Planifica la ejecución de una Corrutinas. Retorna un objeto `Task`.

  Bucles de eventos de terceros pueden usar sus propias subclases de `Task` por interoperabilidad. En este caso, el tipo de resultado es una subclase de `Task`.

  Si el argumento name es provisto y no `None`, se establece como el nombre de la tarea usando `Task.set_name()`.

  Distinto en la versión 3.8: Agregado el parámetro `name`.

`loop.``set_task_factory`(factory)

  Establece una fábrica de tareas que será utilizada por `loop.create_task()`.

  Si factory es `None` se establecerá la fábrica de tareas por defecto. En cualquier otro caso, factory debe ser un callable con la misma firma `(loop, coro)`, donde loop es una referencia al bucle de eventos activo y coro es un objeto de corrutina. El ejecutable debe retornar una objeto `asyncio.Future` compatible.

`loop.``get_task_factory`()

  Retorna una fábrica de tareas o `None` si la predefinida está en uso.

### Abriendo conexiones de red

coroutine `loop.``create_connection`(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None)

  Abre una conexión de transmisión de transporte a una dirección especificada por host y port.

  La familia de sockets puede ser tanto `AF_INET` como `AF_INET6` dependiendo de host (o del argumento family si es que fue provisto).

  El tipo de socket será `SOCK_STREAM`.

  protocol_factory debe ser un ejecutable que retorna una implementación del asyncio protocol.

  Este método tratará de establecer la conexión en un segundo plano. Cuando es exitosa, retorna un par `(transport, protocol)`.

  La sinopsis cronológica de las operaciones subyacentes es como sigue:

  1. La conexión es establecida y un transport es creado para ello.

  2. protocol_factory es llamado sin argumentos y se espera que retorne una instancia de protocol.

  3. La instancia del protocolo se acopla con el transporte mediante el llamado de su método `connection_made()`.

  4. Una tupla `(transport, protocol)` es retornada cuando se tiene éxito.

  El transporte creado es una transmisión (stream) bidireccional que depende de la implementación.

  Otros argumentos:

  - ssl: si se provee y no es falso, un transporte SSL/TLS es creado (de manera predeterminada se crea un transporte TCP plano). Si ssl es un objeto `ssl.SSLContext`, este contexto es utilizado para crear el transporte; si ssl es `True`, se utiliza un contexto predeterminado retornado por `ssl.create_default_context()`.

    Ver también

    Consideraciones de seguridad SSL/TLS

  - server_hostname establece o reemplaza el nombre de servidor (hostname) contra el cual el certificado del servidor de destino será comparado. Sólo debería ser pasado si ssl no es `None`. De manera predeterminada es usado el valor del argumento host. Si host está vacío, no hay valor predeterminado y debes pasar un valor para server_hostname. Si server_hostname es una cadena vacía, la comparación de nombres de servidores es deshabilitada (lo que es un riesgo de seguridad serio, permitiendo potenciales ataques de hombre-en-el-medio, man-in-the-middle attacks).

  - family, proto, flags son dirección de familia, protocolo y banderas opcionales que serán pasadas a través de getaddrinfo() para la resolución de host. Si están dados, todos ellos deberían ser enteros de las constantes del módulo `socket` correspondiente.

  - happy_eyeballs_delay, if given, enables Happy Eyeballs for this connection. It should be a floating-point number representing the amount of time in seconds to wait for a connection attempt to complete, before starting the next attempt in parallel. This is the «Connection Attempt Delay» as defined in RFC 8305. A sensible default value recommended by the RFC is `0.25` (250 milliseconds).

  - interleave controla reordenamientos de dirección cuando un nombre de servidor resuelve a múltiples direcciones IP. Si es `0` o no es especificado, no se hace ningún reordenamiento, y las direcciones son intentadas en el orden retornado por `getaddrinfo()`. Si un entero positivo es especificado, las direcciones son intercaladas por dirección de familia, y el entero dado es interpretado como «Número de familias de la primera dirección» (First Address Family Count) como es definida en RFC 8305. El valor predefinido es `0` si happy_eyeballs_delay no es especificado, y `1` si lo es.

  - sock, si está dado, debe ser un objeto `socket.socket` existente y ya conectado, que será utilizado por el transporte. Si sock es dado, ningún host, port, family, proto, flags, happy_eyeballs_delay, interleave o local_addr deben ser especificados.

  - local_addr, si está dado, es una tupla `(local_host, local_port)``usada para enlazar el socket localmente. Los *local_host* y *local_port* son buscados usando ``getaddrinfo()`, de manera similar que con host y puerto.

  - ssl_handshake_timeout es (para una conexión TLS) el tiempo en segundos a esperar que se complete el apretón de manos (handshake) TLS antes de abortar la conexión. `60.0` segundos si es `None` (predefinido).

  Nuevo en la versión 3.8: Agregados los parámetros happy_eyeballs_delay y interleave.

  Algoritmo de Globos Oculares Felices (Happy Eyeballs): Éxito con Servidores de Doble-Pila (Dual-Stack Hosts). Cuando la ruta IPv4 y el protocolo de un servidor están funcionando, pero la ruta IPv6 y el protocolo no están funcionando, una aplicación del cliente de doble-pila experimenta una demora de conexión significante en comparación con un cliente sólo de IPv4. Esto no es deseable porque causa que el cliente de doble-pila tenga la peor experiencia de usuario. Este documento especifica requerimientos para algoritmos que reducen esta demora visible por el usuario, y provee un algoritmo.

  Para mas información: https://tools.ietf.org/html/rfc6555

  Nuevo en la versión 3.7: El parámetro ssl_handshake_timeout.

  Distinto en la versión 3.6: La opción del socket `TCP_NODELAY` es establecida de manera predeterminada para todas las conexiones TCP.

  Distinto en la versión 3.5: Agregado el soporte para SSL/TLS en `ProactorEventLoop`.

  Ver también

  La función `open_connection()` es una API alternativa de alto nivel. Retorna un par de (`StreamReader`, `StreamWriter`) que puede ser usado directamente en código async/await.

coroutine `loop.``create_datagram_endpoint`(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_address=None, reuse_port=None, allow_broadcast=None, sock=None)

  Nota

  El parámetro reuse_address ya no es soportado, como utiliza `SO_REUSEADDR` plantea un problema de seguridad importante para UDP. Pasando explícitamente `reuse_address=True` lanzará una excepción.

  Cuando múltiples procesos con UIDs diferentes asignan sockets a una misma dirección socket UDP con `SO_REUSEADDR`, los paquetes entrantes pueden distribuirse aleatoriamente entre los sockets.

  Para plataformas soportadas, reuse_port puede ser utilizado como un reemplazo para funcionalidades similares. Con reuse_port, `SO_REUSEPORT` es usado en su lugar, que específicamente previene que procesos con distintos UIDs asignen sockets a la misma dirección de socket.

  Crea un datagrama de conexión.

  La familia de socket puede ser tanto `AF_INET`, `AF_INET6`, como `AF_UNIX`, dependiendo de host (o del argumento family, si fue provisto).

  El tipo de socket será `SOCK_DGRAM`.

  protocol_factory debe ser un ejecutable que retorne una implementación de protocol.

  Una tupla de `(transport, protocol)` es retornada cuando se tiene éxito.

  Otros argumentos:

  - local_addr, si está dado, es una tupla `(local_host, local_port)` usada para enlazar el socket localmente. Los local_host y local_port son buscados utilizando `getaddrinfo()`.

  - remote_addr, si está dado, es una tupla `(remote_host, remote_port)` utilizada para conectar el socket a una dirección remota. Los remote_host y remote_port son buscados utilizando `getaddrinfo()`.

  - family, proto, flags son direcciones de familia, protocolo y banderas opcionales que serán pasadas a través de `getaddrinfo()` para la resolución de host. Si está dado, estos deben ser todos enteros de las constantes del módulo `socket` correspondiente.

  - reuse_port dice al kernel que habilite este punto de conexión para ser unido al mismo puerto de la misma forma que otros puntos de conexión existentes también están unidos, siempre y cuando todos ellos establezcan esta bandera al ser creados. Esta opción no es soportada en Windows y algunos sistemas Unix. Si la constante `SO_REUSEPORT` no está definida entonces esta funcionalidad no es soportada.

  - allow_broadcast dice al kernel que habilite este punto de conexión para enviar mensajes a la dirección de transmisión (broadcast).

  - sock puede opcionalmente ser especificado para usar un objeto `socket.socket` preexistente y ya conectado que será utilizado por el transporte. Si están especificados, local_addr y remote_addr deben ser omitidos (tienen que ser `None`).

  Refiérase a los ejemplos UDP echo client protocol y UDP echo server protocol.

  Distinto en la versión 3.4.4: Los parámetros family, proto, flags, reuse_address, reuse_port, allow_broadcast y sock fueron agregados.

  Distinto en la versión 3.8.1: El parámetro reuse_address ya no es soportado debido a problemas de seguridad.

  Distinto en la versión 3.8: Se agregó soporte para Windows.

coroutine `loop.``create_unix_connection`(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None)

  Crear una conexión Unix.

  La familia de sockets será `AF_UNIX`; el tipo de socket será `SOCK_STREAM`.

  Una tupla de `(transport, protocol)` es retornada cuando se tiene éxito.

  path es el nombre de un dominio de un socket Unix y es requerido, a menos que un parámetro sock sea especificado. Los socket Unix abstractos, `str`, `bytes`, y `Path` son soportados.

  Vea la documentación del método `loop.create_connection()` para información acerca de los argumentos de este método.

  Availability: Unix.

  Nuevo en la versión 3.7: El parámetro ssl_handshake_timeout.

  Distinto en la versión 3.7: El parámetro path ahora puede ser un path-like object.

### Creando servidores de red

coroutine `loop.``create_server`(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)

  Crea un servidor TCP (tipo de socket `SOCK_STREAM`) escuchando en port de la dirección host.

  Retorna un objeto `Server`.

  Argumentos:

  - protocol_factory debe ser un ejecutable que retorne una implementación de protocol.

  - El parámetro host puede ser establecido a distintos tipos que determinan donde el servidor estaría escuchando:

    - Si host es una cadena, el servidor TCP está enlazado a una sola interfaz de red especificada por host.

    - Si host es una secuencia de cadenas, el servidor TCP está enlazado a todas las interfaces de red especificadas por la secuencia.

    - Si host es una cadena vacía o `None`, se asumen todas las interfaces y una lista con múltiples sockets será retornada (mas probablemente uno para IPv4 y otro para IPv6).

  - family puede ser establecido como `socket.AF_INET` o `AF_INET6` para forzar al socket a usar IPv4 o IPv6. Si no es establecido, la family será determinada por medio del nombre del host (por defecto será `AF_UNSPEC`).

  - flags es una máscara de bits para `getaddrinfo()`.

  - sock puede ser especificado opcionalmente para usar objetos socket preexistentes. Si se utiliza, entonces host y port no deben ser especificados.

  - backlog es el número máximo de conexiones encoladas pasadas a `listen()` (el valor predeterminado es 100).

  - ssl puede ser establecido como una instancia de `SSLContext` para habilitar TLS sobre las conexiones aceptadas.

  - reuse_address indica al kernel que reutilice un socket local en estado `TIME_WAIT`, sin esperar que su plazo de ejecución expire. Si no es especificado será establecido automáticamente como `True` en Unix.

  - reuse_port dice al kernel que habilite este punto de conexión para ser unido al mismo puerto de la misma forma que otros puntos de conexión existentes también están unidos, siempre y cuando todos ellos establezcan esta bandera al ser creados.

  - ssl_handshake_timeout es (para un servidor TLS) el tiempo en segundos a esperar por el apretón de manos (handshake) TLS a ser completado antes de abortar la conexión. `60.0` si es `None` (su valor predeterminado).

  - start_serving establecido como `True` (de manera predeterminada) produce que los servidores creados comiencen a aceptar conexiones inmediatamente. Si es establecido como `False`, el usuario debe esperar por `Server.start_serving()` o `Server.serve_forever()` para que el servidor comience a aceptar conexiones.

  Nuevo en la versión 3.7: Agregados los parámetros ssl_handshake_timeout y start_serving.

  Distinto en la versión 3.6: La opción del socket `TCP_NODELAY` es establecida de manera predeterminada para todas las conexiones TCP.

  Distinto en la versión 3.5: Agregado el soporte para SSL/TLS en `ProactorEventLoop`.

  Distinto en la versión 3.5.1: El parámetro host puede ser una secuencia de cadenas.

  Ver también

  La función `start_server()` es una API alternativa de alto nivel que retorna un par de `StreamReader` y `StreamWriter` que pueden ser usados en código async/await.

coroutine `loop.``create_unix_server`(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)

  Similar a `loop.create_server()` pero funciona con la familia de sockets `AF_UNIX`.

  path es el nombre de un dominio de socket Unix, y es requerido a menos que el argumento sock sea provisto. Son soportados sockets unix abstractos, `str`, `bytes`, y rutas `Path`.

  Vea la documentación de el método `loop.create_server()` para mas información acerca de los argumentos de este método.

  Availability: Unix.

  Nuevo en la versión 3.7: Los parámetros ssl_handshake_timeout*y *start_serving.

  Distinto en la versión 3.7: El parámetro path ahora puede ser un objeto `Path`.

coroutine `loop.``connect_accepted_socket`(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None)

  Envuelve una conexión ya aceptada en un par de transporte/protocolo.

  Este método puede ser usado por servidores que acepten conexiones por fuera de asyncio, pero que usen asyncio para manejarlas.

  Parámetros:

  - protocol_factory debe ser un ejecutable que retorne una implementación de protocol.

  - sock es un objeto socket preexistente retornado por `socket.accept`.

  - ssl puede ser establecido como un `SSLContext` para habilitar SSL sobre las conexiones aceptadas.

  - ssl_handshake_timeout es (para una conexión SSL) el tiempo en segundos que se esperará para que se complete el apretón de manos (handshake) SSL antes de abortar la conexión. `60.0` si es `None` (su valor predeterminado).

  Retorna un par `(transport, protocol)`.

  Nuevo en la versión 3.7: El parámetro ssl_handshake_timeout.

  Nuevo en la versión 3.5.3.

### Transfiriendo archivos

coroutine `loop.``sendfile`(transport, file, offset=0, count=None, *, fallback=True)

  Envía un file a través de un transport. Retorna el numero total de bytes enviados.

  El método usa `os.sendfile()` de alto rendimiento si está disponible.

  file debe ser un objeto de archivo regular abierto en modo binario.

  offset indica desde donde se empezará a leer el archivo. Si es especificado, count es el número total de bytes a transmitir en contraposición con enviar el archivo hasta que se alcance EOF. La posición del archivo es actualizada siempre, incluso cuando este método genere un error, y `file.tell()` puede ser usado para obtener el número de bytes enviados hasta el momento.

  fallback establecido como `True` hace que asyncio lea y envíe el archivo manualmente cuando la plataforma no soporta la llamada de envío de archivos del sistema (por ejemplo, Windows o sockets SSL en Unix).

  Lanza `SendfileNotAvailableError` si el sistema no soporta la llamada de envío de archivos del sistema y fallback es `True`.

  Nuevo en la versión 3.7.

### Actualización de TLS

coroutine `loop.``start_tls`(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None)

  Actualiza una conexión basada en transporte ya existente a TLS.

  Retorna una nueva instancia de transporte, que el protocol debe empezar a usar inmediatamente después del await. La instancia transport pasada al método start_tls nunca debe ser usada de nuevo.

  Parámetros:

  - Las instancias transport y protocol que retornan los métodos como `create_server()` y `create_connection()`.

  - sslcontext: una instancia configurada de `SSLContext`.

  - server_side pasa True cuando se actualiza una conexión del lado del servidor (como en el caso de una creada por `create_server()`).

  - server_hostname: establece o reemplaza el nombre del host contra el cual se compara el certificado del servidor de destino.

  - ssl_handshake_timeout es (para una conexión TLS) el tiempo en segundos a esperar que se complete el apretón de manos (handshake) TLS antes de abortar la conexión. `60.0` segundos si es `None` (predefinido).

  Nuevo en la versión 3.7.

### Viendo descriptores de archivos

`loop.``add_reader`(fd, callback, *args)

  Empieza a monitorear el descriptor de archivos fd para disponibilidad de lectura e invoca callback con los argumentos especificados una vez que fd está habilitado para ser leído.

`loop.``remove_reader`(fd)

  Deja de monitorear el descriptor de archivos fd para disponibilidad de lectura.

`loop.``add_writer`(fd, callback, *args)

  Empieza a monitorear el descriptor de archivos fd para disponibilidad de escritura e invoca callback con los argumentos especificados una vez que fd está habilitado para ser escrito.

  Use `functools.partial()` para pasar argumentos de palabra clave a callback.

`loop.``remove_writer`(fd)

  Deja de monitorear el descriptor de archivos fd para disponibilidad de escritura.

Vea también la sección Soporte de plataforma para algunas limitaciones de estos métodos.

### Trabajar con objetos sockets directamente

En general, implementaciones de protocolo que usen APIs basadas en transporte como `loop.create_connection()` y `loop.create_server()` son mas rápidas que aquellas implementaciones que trabajan con directamente con sockets. De cualquier forma, hay algunos casos de uso en los cuales el rendimiento no es crítico, y trabajar directamente con objetos `socket` es mas conveniente.

coroutine `loop.``sock_recv`(sock, nbytes)

  Recibe hasta nbytes de sock. Versión asíncrona de `socket.recv()`.

  Retorna los datos recibidos como un objeto bytes.

  sock debe ser un socket no bloqueante.

  Distinto en la versión 3.7: A pesar de que este método siempre fue documentado como un método de corrutina, los lanzamientos previos a Python 3.7 retornaban un `Future`. Desde Python 3.7 este es un método `async def`.

coroutine `loop.``sock_recv_into`(sock, buf)

  Recibe datos desde sock en el búfer buf. Modelado después del método bloqueante `socket.recv_into()`.

  Retorna el número de bytes escritos en el búfer.

  sock debe ser un socket no bloqueante.

  Nuevo en la versión 3.7.

coroutine `loop.``sock_sendall`(sock, data)

  Envía data al socket sock. Versión asíncrona de `socket.sendall()`.

  Este método continua enviando al socket hasta que se hayan enviado todos los datos en data u ocurra un error. `None` es retornado cuando se tiene éxito. Cuando ocurre un error, se lanza una excepción. Adicionalmente, no hay manera de determinar cuantos datos, si es que se hubo alguno, se procesaron correctamente por el extremo receptor de la conexión.

  sock debe ser un socket no bloqueante.

  Distinto en la versión 3.7: A pesar de que este método siempre fue documentado como un método de corrutina, antes de Python 3.7 retorna un `Future`. Desde Python 3.7, este es un método `async def`.

coroutine `loop.``sock_connect`(sock, address)

  Conecta sock a un socket remoto en address.

  Versión asíncrona de `socket.connect()`.

  sock debe ser un socket no bloqueante.

  Distinto en la versión 3.5.2: `address` ya no necesita ser resuelto. `sock_connect` va a intentar verificar si address ya fue resuelto a partir del llamado de `socket.inet_pton()`. Si no lo fue, se utilizará `loop.getaddrinfo()` ara resolver address.

  Ver también

  `loop.create_connection()` y `asyncio.open_connection()`.

coroutine `loop.``sock_accept`(sock)

  Acepta una conexión. Modelado después del método bloqueante `socket.accept()`.

  The socket must be bound to an address and listening for connections. The return value is a pair `(conn, address)` where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

  sock debe ser un socket no bloqueante.

  Distinto en la versión 3.7: A pesar de que este método siempre fue documentado como un método de corrutina, antes de Python 3.7 retorna un `Future`. Desde Python 3.7, este es un método `async def`.

  Ver también

  `loop.create_server()` y `start_server()`.

coroutine `loop.``sock_sendfile`(sock, file, offset=0, count=None, *, fallback=True)

  Envía un archivo usando `os.sendfile` de alto rendimiento si es posible. Retorna el número total de bytes enviados.

  Versión asíncrona de `socket.sendfile()`.

  sock debe ser un `socket.SOCK_STREAM` `socket` no bloqueante.

  file debe ser un objeto de archivo regular abierto en modo binario.

  offset indica desde donde se empezará a leer el archivo. Si es especificado, count es el número total de bytes a transmitir en contraposición con enviar el archivo hasta que se alcance EOF. La posición del archivo es actualizada siempre, incluso cuando este método genere un error, y `file.tell()` puede ser usado para obtener el número de bytes enviados hasta el momento.

  fallback, cuando es establecida como `True`, hace que asyncio lea y escriba el archivo manualmente cuando el sistema no soporta la llamada de envío de archivos del sistema (por ejemplo, Windows o sockets SSL en Unix).

  Lanza `SendfileNotAvailableError` si el sistema no soporta la llamada de envío de archivos del sistema sendfile y fallback es `False`.

  sock debe ser un socket no bloqueante.

  Nuevo en la versión 3.7.

### DNS

coroutine `loop.``getaddrinfo`(host, port, *, family=0, type=0, proto=0, flags=0)

  Versión asíncrona de `socket.getaddrinfo()`.

coroutine `loop.``getnameinfo`(sockaddr, flags=0)

  Asynchronous version of `socket.getnameinfo()`.

Distinto en la versión 3.7: Ambos métodos getaddrinfo y getnameinfo siempre fueron documentados para retornar una corrutina, pero antes de Python 3.7 retornaban, de hecho, objetos `Future`. A partir de Python 3.7, ambos métodos son corrutinas.

### Trabajando con tuberías

coroutine `loop.``connect_read_pipe`(protocol_factory, pipe)

  Registra el fin de lectura de pipe en el bucle de eventos.

  protocol_factory debe ser un ejecutable que retorna una implementación del asyncio protocol.

  pipe es un objeto de tipo archivo.

  Retorna un par `(transport, protocol)`, donde transport soporta la interface `ReadTransport` y protocol es un objeto instanciado por protocol_factory.

  Con el bucle de eventos `SelectorEventLoop`, el pipe es establecido en modo no bloqueante.

coroutine `loop.``connect_write_pipe`(protocol_factory, pipe)

  Registra el fin de escritura de pipe en el bucle de eventos.

  protocol_factory debe ser un ejecutable que retorna una implementación del asyncio protocol.

  pipe es un objeto de tipo archivo.

  Retorna un par `(transport, protocol)`, donde transport soporta la interface `WriteTransport` y protocol es un objeto inicializado por protocol_factory.

  Con el bucle de eventos `SelectorEventLoop`, el pipe es establecido en modo no bloqueante.

Nota

`SelectorEventLoop` no soporta los métodos anteriores en windows. En su lugar, use `ProactorEventLoop` para Windows.

Ver también

Los métodos `loop.subprocess_exec()` y `loop.subprocess_shell()`.

### Señales Unix

`loop.``add_signal_handler`(signum, callback, *args)

  Establece callback como el gestor para la señal signum.

  La llamada será invocada por loop, junto con otras llamadas encoladas y corrutinas ejecutables de ese bucle de eventos. A menos que los gestores de señal la registren usando `signal.signal()`, una llamada registrada con esta función tiene permitido interactuar con el bucle de eventos.

  Lanza `ValueError` si el número de señal es invalido o inalcanzable. Lanza `RuntimeError` si hay algún problema preparando el gestor.

  Use `functools.partial()` para pasar argumentos de palabra clave a callback.

  Como `signal.signal()`, esta función debe ser invocada en el hilo principal.

`loop.``remove_signal_handler`(sig)

  Elimina el gestor para la señal sig.

  Retorna `True` si el gestor de señal fue eliminado, o `False` si no se estableció gestor para la señal dada.

  Availability: Unix.

Ver también

El módulo `signal`.

### Ejecutando código en un hilos o grupos de procesos

awaitable `loop.``run_in_executor`(executor, func, *args)

  Arrange for func to be called in the specified executor.

  El argumento executor debe ser una instancia de `concurrent.futures.Executor`. El ejecutor predeterminado es usado si executor es `None`.

  Ejemplo:

      import asyncio
      import concurrent.futures

      def blocking_io():
          # File operations (such as logging) can block the
          # event loop: run them in a thread pool.
          with open('/dev/urandom', 'rb') as f:
              return f.read(100)

      def cpu_bound():
          # CPU-bound operations will block the event loop:
          # in general it is preferable to run them in a
          # process pool.
          return sum(i * i for i in range(10 ** 7))

      async def main():
          loop = asyncio.get_running_loop()

          ## Options:

          # 1. Run in the default loop's executor:
          result = await loop.run_in_executor(
              None, blocking_io)
          print('default thread pool', result)

          # 2. Run in a custom thread pool:
          with concurrent.futures.ThreadPoolExecutor() as pool:
              result = await loop.run_in_executor(
                  pool, blocking_io)
              print('custom thread pool', result)

          # 3. Run in a custom process pool:
          with concurrent.futures.ProcessPoolExecutor() as pool:
              result = await loop.run_in_executor(
                  pool, cpu_bound)
              print('custom process pool', result)

      asyncio.run(main())

  Este método retorna un objeto `asyncio.Future`.

  Use `functools.partial()` para pasar argumentos de palabra clave a func.

  Distinto en la versión 3.5.3: `loop.run_in_executor()` no longer configures the `max_workers` of the thread pool executor it creates, instead leaving it up to the thread pool executor (`ThreadPoolExecutor`) to set the default.

`loop.``set_default_executor`(executor)

  Establece executor como el ejecutor predeterminado utilizado por `run_in_executor()`. executor debe ser una instancia de `ThreadPoolExecutor`.

  Obsoleto desde la versión 3.8: Usar un ejecutor que no es una instancia de `ThreadPoolExecutor` es obsoleto y disparará un error en Python 3.9.

  executor debe ser una instancia de `concurrent.futures.ThreadPoolExecutor`.

### API para manejo de errores

Permite personalizar como son manejadas las excepciones en el bucle de eventos.

`loop.``set_exception_handler`(handler)

  Establece handler como el nuevo gestor de excepciones del bucle de eventos.

  Si handler es `None`, se establecerá el gestor de excepciones predeterminado. De otro modo, handler debe ser un invocable con la misma firma `(loop, context)`, donde `loop` es una referencia al bucle de eventos activo, y `context` es un objeto `dict` que contiene los detalles de la excepción (vea la documentación de `call_exception_handler()` para detalles acerca del contexto).

`loop.``get_exception_handler`()

  Retorna el gesto de excepciones actual, o `None` si no fue establecido ningún gestor de excepciones personalizado.

  Nuevo en la versión 3.5.2.

`loop.``default_exception_handler`(context)

  Gestor de excepciones por defecto.

  Esto es llamado cuando ocurre una excepción y no se estableció ningún gestor de excepciones. Esto puede ser llamado por un gestor de excepciones personalizado que quiera cambiar el comportamiento del gestor predeterminado.

  El parámetro context tiene el mismo significado que en `call_exception_handler()`.

`loop.``call_exception_handler`(context)

  Llama al gestor de excepciones del bucle de eventos actual.

  context es un objeto `dict` conteniendo las siguientes claves (en futuras versiones de Python podrían introducirse nuevas claves):

  - “message”: Mensaje de error;

  - “exception” (opcional): Objeto de excepción;

  - “future” (opcional): instancia de `asyncio.Future`;

  - “handle” (opcional): instancia de `asyncio.Handle`;

  - “protocol” (opcional): instancia de Protocol;

  - “transport” (opcional): instancia de Transport;

  - “socket” (opcional): instancia de `socket.socket`.

  Nota

  Este método no debe ser sobrecargado en bucles de eventos en subclase. Para gestión de excepciones personalizadas, use el método `set_exception_handler()`.

### Habilitando el modo depuración

`loop.``get_debug`()

  Obtiene el modo depuración (`bool`) del bucle de eventos.

  El valor predeterminado es `True` si la variable de entorno `PYTHONASYNCIODEBUG` es establecida a una cadena no vacía, de otro modo será `False`.

`loop.``set_debug`(enabled: bool)

  Establece el modo de depuración del bucle de eventos.

  Distinto en la versión 3.7: La nueva opción de linea de comandos `-X dev` ahora también puede ser utilizada para habilitar el modo depuración.

Ver también

El modo depuración de asyncio.

### Ejecutando Subprocesos

Los métodos descritos en esta subsección son de bajo nivel. En código async/await regular considere usar las convenientes funciones de alto nivel `asyncio.create_subprocess_shell()` y `asyncio.create_subprocess_exec()`.

Nota

El bucle de eventos predeterminado de asyncio en Windows no soporta subprocesos. Vea Soporte de subprocesos en Windows para mas detalles.

coroutine `loop.``subprocess_exec`(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

  Crea un subproceso de uno o mas argumentos de cadena especificados por args.

  args debe ser una lista de cadenas representadas por:

  - `str`;

  - o `bytes`, codificados a la codificación del sistema de archivos.

  La primer cadena especifica el programa ejecutable, y las cadenas restantes especifican los argumentos. En conjunto, los argumentos de cadena forman el `argv` del programa.

  Esto es similar a la clase de la librería estándar `subprocess.Popen` llamada con `shell=False` y la lista de cadenas pasadas como el primer argumento; de cualquier forma, cuando `Popen` toma un sólo argumento que es una lista de cadenas, subprocess_exec toma múltiples cadenas como argumentos.

  El protocol_factory debe ser un ejecutable que retorne una subclase de la clase `asyncio.SubprocessProtocol`.

  Otros parámetros:

  - stdin puede ser cualquier de estos:

    - un objeto de tipo archivo representando una tubería que será conectada al flujo de entrada estándar del subproceso utilizando `connect_write_pipe()`

    - la constante `subprocess.PIPE` (predeterminado) que creará una tubería nueva y la conectará,

    - el valor `None` que hará que el subproceso herede el descriptor de archivo de este proceso

    - la constante `subprocess.DEVNULL` que indica que el archivo especial `os.devnull` será utilizado

  - stdout puede ser cualquier de estos:

    - un objeto de tipo archivo representando una tubería que será conectada al flujo de salida estándar del subproceso utilizando `connect_write_pipe()`

    - la constante `subprocess.PIPE` (predeterminado) que creará una tubería nueva y la conectará,

    - el valor `None` que hará que el subproceso herede el descriptor de archivo de este proceso

    - la constante `subprocess.DEVNULL` que indica que el archivo especial `os.devnull` será utilizado

  - stderr puede ser cualquier de estos:

    - un objeto de tipo archivo representando una tubería que será conectada al flujo de error estándar del subproceso utilizando `connect_write_pipe()`

    - la constante `subprocess.PIPE` (predeterminado) que creará una tubería nueva y la conectará,

    - el valor `None` que hará que el subproceso herede el descriptor de archivo de este proceso

    - la constante `subprocess.DEVNULL` que indica que el archivo especial `os.devnull` será utilizado

    - la constante `subprocess.STDOUT` que conectará el flujo de errores predeterminado al flujo de salida predeterminado del proceso

  - El resto de argumentos de palabra clave son pasados a `subprocess.Popen` sin interpretación, excepto por bufsize, universal_newlines, shell, text, encoding y errors, que no deben ser especificados en lo absoluto.

    La API subproceso `asyncio` no soporta decodificar los flujos como texto. `bytes.decode()` puede ser usado para convertir a texto los bytes retornados por el flujo.

  Vea el constructor de la clase `subprocess.Popen` para documentación acerca de otros argumentos.

  Retorna un par de `(transport, protocol)`, donde transport se ajusta a la clase base `asyncio.SubprocessTransport` y protocol es un objeto instanciado por protocol_factory.

coroutine `loop.``subprocess_shell`(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

  Crea un subproceso desde cmd, que puede ser una cadena `str` o `bytes` codificado a la codificación del sistema de archivos, usando la sintaxis «shell» de la plataforma.

  Esto es similar a la clase de la librería estándar `subprocess.Popen` llamada con `shell=True`.

  El protocol_factory debe ser un ejecutable que retorne una subclase de la clase `asyncio.SubprocessProtocol`.

  Vea `subprocess_exec()` para mas detalles acerca de los argumentos restantes.

  Retorna un par de `(transport, protocol)`, donde transport se ajusta a la clase base `SubprocessTransport` y protocol es un objeto instanciado por protocol_factory.

Nota

Es responsabilidad de la aplicación asegurar que todos los espacios en blanco y caracteres especiales estén escapados correctamente para evitar vulnerabilidades de inyección de código. La función `shlex.quote()` puede ser usada para escapar apropiadamente espacios en blanco y caracteres especiales en cadenas que van a ser usadas para construir comandos de consola.

## Gestores de llamadas

class `asyncio.``Handle`

  Un objeto de contenedor de llamada retornado por `loop.call_soon()`, `loop.call_soon_threadsafe()`.

  `cancel`()

    Cancela la llamada. Si la llamada ya fue cancelada o ejecutada, este método no tiene efecto.

  `cancelled`()

    Retorna `True` si la llamada fue cancelada.

    Nuevo en la versión 3.7.

class `asyncio.``TimerHandle`

  Un objeto de contenedor de llamada retornado por `loop.call_later()`, and `loop.call_at()`.

  Esta clase es una subclase de `Handle`.

  `when`()

    Retorna el tiempo de una llamada planificada como `float` segundos.

    El tiempo es una marca de tiempo absoluta, usando la misma referencia de tiempo que `loop.time()`.

    Nuevo en la versión 3.7.

## Objetos Servidor

Los objetos de servidor son creados por las funciones `loop.create_server()`, `loop.create_unix_server()`, `start_server()`, y `start_unix_server()`.

No instanciar la clase directamente.

class `asyncio.``Server`

  Los objetos Server son gestores de asíncronos de contexto. Cuando son usados en una declaración `async with`, está garantizado que el objeto Servidor está cerrado y no está aceptando nuevas conexiones cuando la declaración `async with` es completada:

      srv = await loop.create_server(...)

      async with srv:
          # some code

      # At this point, srv is closed and no longer accepts new connections.

  Distinto en la versión 3.7: El objeto Servidor es un gestor asíncrono de contexto desde Python 3.7.

  `close`()

    Deja de servir: deja de escuchar sockets y establece el atributo `sockets` a `None`.

    Los sockets que representan conexiones entrantes existentes de clientes se dejan abiertas.

    El servidor es cerrado de manera asíncrona, usa la corrutina `wait_closed()` para esperar hasta que el servidor esté cerrado.

  `get_loop`()

    Retorna el bucle de eventos asociado con el objeto Servidor.

    Nuevo en la versión 3.7.

  coroutine `start_serving`()

    Comienza a aceptar conexiones.

    Este método es idempotente, así que puede ser llamado cuando el servidor ya está sirviendo.

    El parámetro sólo de palabra clave start_serving de `loop.create_server()` y `asyncio.start_server()` permite crear un objeto Servidor que no está aceptando conexiones inicialmente. En este caso `Server.start_serving()`, o `Server.serve_forever()` pueden ser usados para hacer que el servidor empiece a aceptar conexiones.

    Nuevo en la versión 3.7.

  coroutine `serve_forever`()

    Comienza a aceptar conexiones hasta que la corrutina sea cancelada. La cancelación de la tarea `serve_forever` hace que el servidor sea cerrado.

    Este método puede ser llamado si el servidor ya está aceptando conexiones. Solamente una tarea `serve_forever` puede existir para un objeto Server.

    Ejemplo:

        async def client_connected(reader, writer):
            # Communicate with the client with
            # reader/writer streams.  For example:
            await reader.readline()

        async def main(host, port):
            srv = await asyncio.start_server(
                client_connected, host, port)
            await srv.serve_forever()

        asyncio.run(main('127.0.0.1', 0))

    Nuevo en la versión 3.7.

  `is_serving`()

    Retorna `True` si el servidor está aceptando nuevas conexiones.

    Nuevo en la versión 3.7.

  coroutine `wait_closed`()

    Espera hasta que el método `close()` se complete.

  `sockets`

    Lista todos los objetos `socket.socket` en los que el servidor está escuchando.

    Distinto en la versión 3.7: Antes de Python 3.7 `Server.sockets` solía retornar directamente una lista interna de servidores socket. En 3.7 se retorna una copia de esa lista.

## Implementaciones del bucle de eventos

asyncio viene con dos implementaciones diferentes del bucle de eventos: `SelectorEventLoop` y `ProactorEventLoop`.

De manera predefinida asyncio está configurado para usar `SelectorEventLoop` en Unix y `ProactorEventLoop` en Windows.

class `asyncio.``SelectorEventLoop`

  Un bucle de eventos basado en el módulo `selectors`.

  Usa el selector disponible mas eficiente para la plataforma dada. También es posible configurar manualmente la implementación exacta del selector a utilizar:

      import asyncio
      import selectors

      selector = selectors.SelectSelector()
      loop = asyncio.SelectorEventLoop(selector)
      asyncio.set_event_loop(loop)

  Disponibilidad: Unix, Windows.

class `asyncio.``ProactorEventLoop`

  Un bucle de eventos para Windows que usa «E/S Puertos de Finalización» (IOCP).

  Disponibilidad: Windows.

  Ver también

  Documentaci´on de MSDN sobre E/S Puertos de Finalización.

class `asyncio.``AbstractEventLoop`

  Clase base abstracta para bucles de evento compatibles con asyncio.

  La sección Métodos del bucle de eventos lista todos los métodos que como implementación alternativa de `AbstractEventLoop` debería haber estado definido.

## Examples

Nótese que todos los ejemplos en esta sección muestran a propósito como usar las APIs de bucle de eventos de bajo nivel, como ser `loop.run_forever()` y `loop.call_soon()`. Aplicaciones asyncio modernas raramente necesitan ser escritas de esta manera; considere utilizar funciones de alto nivel como `asyncio.run()`.

### Hola Mundo con call_soon()

Un ejemplo usando el método `loop.call_soon()` para planificar una llamada. La llamada muestra `"Hello World"` y luego para el bucle de eventos:

    import asyncio

    def hello_world(loop):
        """A callback to print 'Hello World' and stop the event loop"""
        print('Hello World')
        loop.stop()

    loop = asyncio.get_event_loop()

    # Schedule a call to hello_world()
    loop.call_soon(hello_world, loop)

    # Blocking call interrupted by loop.stop()
    try:
        loop.run_forever()
    finally:
        loop.close()

Ver también

Un ejemplo similar de Hola Mundo creado con una corrutina y la función `run()`.

### Muestra la fecha actual con call_later()

Un ejemplo de llamada mostrando la fecha actual cada un segundo. La llamada usa el método `loop.call_later()` para volver a planificarse después de 5 segundos, y después para el bucle de eventos:

    import asyncio
    import datetime

    def display_date(end_time, loop):
        print(datetime.datetime.now())
        if (loop.time() + 1.0) < end_time:
            loop.call_later(1, display_date, end_time, loop)
        else:
            loop.stop()

    loop = asyncio.get_event_loop()

    # Schedule the first call to display_date()
    end_time = loop.time() + 5.0
    loop.call_soon(display_date, end_time, loop)

    # Blocking call interrupted by loop.stop()
    try:
        loop.run_forever()
    finally:
        loop.close()

Ver también

Un ejemplo similar a fecha actual creado con una corrutina y la función `run()`.

### Mirar un descriptor de archivo para leer eventos

Espera hasta que el descriptor de archivo reciba algún dato usando el método `loop.add_reader()` y entonces cierra el bucle de eventos:

    import asyncio
    from socket import socketpair

    # Create a pair of connected file descriptors
    rsock, wsock = socketpair()

    loop = asyncio.get_event_loop()

    def reader():
        data = rsock.recv(100)
        print("Received:", data.decode())

        # We are done: unregister the file descriptor
        loop.remove_reader(rsock)

        # Stop the event loop
        loop.stop()

    # Register the file descriptor for read event
    loop.add_reader(rsock, reader)

    # Simulate the reception of data from the network
    loop.call_soon(wsock.send, 'abc'.encode())

    try:
        # Run the event loop
        loop.run_forever()
    finally:
        # We are done. Close sockets and the event loop.
        rsock.close()
        wsock.close()
        loop.close()

Ver también

- Un ejemplo similar usando transportes, protocolos y el método `loop.create_connection()`.

- Otro ejemplo similar usando la función de alto nivel `asyncio.open_connection()` y transmisiones.

### Establece los gestores de señal para SIGINT y SIGTERM

(Este ejemplo de `signals` solamente funcionan en Unix.)

Registra gestores para las señales `SIGINT` y `SIGTERM` usando el método `loop.add_signal_handler()`:

    import asyncio
    import functools
    import os
    import signal

    def ask_exit(signame, loop):
        print("got signal %s: exit" % signame)
        loop.stop()

    async def main():
        loop = asyncio.get_running_loop()

        for signame in {'SIGINT', 'SIGTERM'}:
            loop.add_signal_handler(
                getattr(signal, signame),
                functools.partial(ask_exit, signame, loop))

        await asyncio.sleep(3600)

    print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
    print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

    asyncio.run(main())