Políticas¶
Una política de bucle de eventos es un objeto global que se utiliza para obtener y establecer el bucle de eventos actual o para crear nuevos bucles de eventos. La política preestablecida puede ser reemplazada con alternativas built-in para usar diferentes implementaciones de bucles de eventos, o sustituida por una política personalizada la cual puede anular estos comportamientos.
El objeto de política obtiene y establece un bucle de eventos separado por contexto. Por defecto, esto se realiza por hilo, aunque las políticas personalizadas pueden definir el contexto de una forma diferente.
Las políticas de bucle de eventos personalizadas pueden controlar el comportamiento de get_event_loop()
, set_event_loop()
, y new_event_loop()
.
Los objetos de política deberían implementar las APIs definidas en la clase abstracta base AbstractEventLoopPolicy
.
Obteniendo y configurando la política¶
Las siguientes funciones pueden ser usadas para obtener y configurar la política de los procesos actuales:
- asyncio.get_event_loop_policy()¶
Retorna la política actual en todo el proceso.
- asyncio.set_event_loop_policy(policy)¶
Establece la política actual en todo el proceso a policy.
Si policy está configurado a
None
, la política por defecto se reestablece.
Objetos de política¶
La clase base de política de bucle de eventos abstractos se define de la siguiente manera:
- class asyncio.AbstractEventLoopPolicy¶
Una clase base abstracta para políticas asyncio.
- get_event_loop()¶
Retorna el bucle de eventos para el contexto actual.
Retorna un objeto bucle de eventos implementando la interfaz
AbstractEventLoop
.Este método nunca debería retornar
None
.Distinto en la versión 3.6.
- set_event_loop(loop)¶
Establece el bucle de eventos para el contexto a loop.
- new_event_loop()¶
Crea y retorna un nuevo objeto de bucle de eventos.
Este método nunca debería retornar
None
.
- get_child_watcher()¶
Retorna un objeto observador de procesos secundarios.
Retorna un objeto observador implementando la interfaz
AbstractChildWatcher
.Esta función es específica de Unix.
Obsoleto desde la versión 3.12.
- set_child_watcher(watcher)¶
Establece el observador de procesos secundarios actuales a watcher.
Esta función es específica de Unix.
Obsoleto desde la versión 3.12.
asyncio se envía con las siguientes políticas integradas:
- class asyncio.DefaultEventLoopPolicy¶
La política por defecto asyncio. Usa
SelectorEventLoop
en Unix yProactorEventLoop
en Windows.No hay necesidad de instalar la política por defecto manualmente. asyncio está configurado para usar la política por defecto automáticamente.
Distinto en la versión 3.8: En Windows,
ProactorEventLoop
ahora se usa por defecto.Obsoleto desde la versión 3.12: El método
get_event_loop()
de la política asyncio predeterminada ahora emite unaDeprecationWarning
si no hay un bucle de eventos actual configurado y decide crear uno. En alguna versión futura de Python, esto se convertirá en un error.
- class asyncio.WindowsSelectorEventLoopPolicy¶
Una política de bucle de eventos alternativa que usa la implementación de bucle de eventos
SelectorEventLoop
.Availability: Windows.
- class asyncio.WindowsProactorEventLoopPolicy¶
Una política de bucle de eventos alternativa que usa la implementación de bucle de eventos
ProactorEventLoop
.Availability: Windows.
Observadores de procesos¶
Un observador de procesos permite personalizar cómo un bucle de eventos monitorea procesos secundarios en Unix. Específicamente, un bucle de eventos necesita saber cuándo un proceso secundario ha terminado.
En asyncio, los procesos secundarios son creados con las funciones créate_subprocess_exec()
y loop.subprocess_exec()
.
asyncio define la clase base abstracta AbstractChildWatcher
, qué observadores de subprocesos deberían implementarse, y tiene cuatro implementaciones diferentes: ThreadedChildWatcher
(configurado para ser usado por defecto), MultiLoopChildWatcher
, SaferChildWatcher
, y FastChildWatcher
.
Mirar también la sección Subprocesos e hilos.
Las siguientes dos funciones pueden ser usadas para personalizar la implementación de observadores de procesos secundarios usados por el bucle de eventos de asyncio:
- asyncio.get_child_watcher()¶
Retorna el observador de procesos secundarios para la política actual.
Obsoleto desde la versión 3.12.
- asyncio.set_child_watcher(watcher)¶
Establece el observador de procesos secundarios actuales a watcher para la política actual. watcher debe implementar métodos definidos en la clase base
AbstractChildWatcher
.Obsoleto desde la versión 3.12.
Nota
Implementaciones de bucles de eventos de terceras partes no deben dar soporte a observadores de procesos secundarios personalizados. Para dichos bucles de eventos, usando set_child_watcher()
podría estar prohibido o no tener efecto.
- class asyncio.AbstractChildWatcher¶
- add_child_handler(pid, callback, *args)¶
Registra un nuevo gestor de proceso secundario.
Arreglo para
callback(pid, returncode, *args)
a ser invocado cuando un proceso con PID igual a pid termina. Especificando otro retrollamada para el mismo proceso reemplaza el gestor previo.El callback invocable debe ser seguro para hilos.
- remove_child_handler(pid)¶
Remueve el gestor para el proceso con PID igual a pid.
La función retorna
True
si el gestor fue removido de forma exitosa,False
si no hubo nada que remover.
- attach_loop(loop)¶
Adjunta el observador a un bucle de eventos.
Si el observador estaba previamente adjuntado a un bucle de eventos, entonces primero es separado antes de adjuntar el nuevo bucle.
Nota: el bucle puede ser
None
.
- is_active()¶
Retorna
True
si el observador está listo para usarse.Generar un nuevo subproceso con observador de procesos secundarios actual inactive lanza
RuntimeError
.Added in version 3.8.
- close()¶
Cierra el observador.
Este método tiene que ser invocado para asegurar que los objetos subyacentes están limpiados.
Obsoleto desde la versión 3.12.
- class asyncio.ThreadedChildWatcher¶
Esta implementación inicia un nuevo hilo esperando para cada subproceso generado.
Trabaja de manera confiable incluso cuando el bucle de eventos asyncio se ejecuta en un hilo de SO no principal.
There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates), but starting a thread per process requires extra memory.
Este observador es usado por defecto.
Added in version 3.8.
- class asyncio.MultiLoopChildWatcher¶
Esta implementación registra un gestor de señal en instanciación
SIGCHLD
. Eso puede romper código de terceras partes que instalen un gestor personalizado para la señalSIGCHLD
.El observador evita interrumpir otro código generando procesos sondeando cada proceso explícitamente en una señal
SIGCHLD
.No hay limitación para ejecutar subprocesos de diferentes hilos una vez el observador es instalado.
The solution is safe but it has a significant overhead when handling a big number of processes (O(n) each time a
SIGCHLD
is received).Added in version 3.8.
Obsoleto desde la versión 3.12.
- class asyncio.SafeChildWatcher¶
Esta implementación usa bucles de eventos activos del hilo principal para gestionar la señal
SIGCHLD
. Si el hilo principal no tiene bucles de eventos en ejecución otro hilo no puede generar un subproceso (RuntimeError
es disparada).El observador evita interrumpir otro código generando procesos sondeando cada proceso explícitamente en una señal
SIGCHLD
.This solution is as safe as
MultiLoopChildWatcher
and has the same O(n) complexity but requires a running event loop in the main thread to work.Obsoleto desde la versión 3.12.
- class asyncio.FastChildWatcher¶
Esta implementación cosecha cada proceso terminado llamando
os.waitpad(-1)
directamente, posiblemente rompiendo otro código generando procesos y esperando por su terminación.There is no noticeable overhead when handling a big number of children (O(1) each time a child terminates).
Esta solución requiere un bucle de eventos ejecutándose en el hilo principal para trabajar, como
SafeChildWatcher
.Obsoleto desde la versión 3.12.
- class asyncio.PidfdChildWatcher¶
Esta implementación sondea los descriptores de archivos de proceso (pidfds) para esperar la terminación del proceso hijo. En ciertos sentidos
PidfdChildWatcher
es una implementación de niño vigilante «Ricitos de oro». No requiere señales o hilos, no interfiere con ningún proceso lanzado fuera del bucle de eventos y escala linealmente con el número de subprocesos lanzados por el bucle de eventos. La principal desventaja es que los pidfds son específicos de Linux y solo funcionan en kernels recientes (5.3+).Added in version 3.9.
Personalizar Políticas¶
Para implementar una nueva política de bucle de eventos, se recomienda heredar DefaultEventLoopPolicy
y sobreescribir los métodos para los cuales se desea una conducta personalizada, por ejemplo:
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
"""Get the event loop.
This may be None or an instance of EventLoop.
"""
loop = super().get_event_loop()
# Do something with loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())