# Políticas

Una política del bucle de eventos es un objeto por proceso que controla la administración del bucle de eventos. Cada bucle de eventos tiene una política por defecto, que puede ser cambiada y editada usando la política de API.

Una política define la noción de contexto y administra un bucle de eventos separado por contexto. La política por defecto define un contexto como el estado actual.

Usando una política de bucle de eventos personalizada, la conducta de las funciones `get_event_loop()`, `set_event_loop()`, y `new_event_loop()` puede ser personalizada.

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.

  `set_child_watcher`(watcher)

    Establece el observador de procesos secundarios actuales a watcher.

    Esta función es específica de Unix.

asyncio se envía con las siguientes políticas integradas:

class `asyncio.``DefaultEventLoopPolicy`

  La política por defecto asyncio. Usa `SelectorEventLoop` en Unix y `ProactorEventLoop` 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.

class `asyncio.``WindowsSelectorEventLoopPolicy`

  Una política de bucle de eventos alternativa que usa la implementación de bucle de eventos `SelectorEventLoop`.

  Disponibilidad: Windows.

class `asyncio.``WindowsProactorEventLoopPolicy`

  Una política de bucle de eventos alternativa que usa la implementación de bucle de eventos `ProactorEventLoop`.

  Disponibilidad: 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.

`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`.

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`.

    Nuevo en la versión 3.8.

  `close`()

    Cierra el observador.

    Este método tiene que ser invocado para asegurar que los objetos subyacentes están limpiados.

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.

  Nuevo en la versión 3.8.

class `asyncio.``MultiLoopChildWatcher`

  This implementation registers a `SIGCHLD` signal handler on instantiation. That can break third-party code that installs a custom handler for `SIGCHLD` signal.

  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.

  La solución es segura pero tiene una sobrecarga significativa cuando se gestiona un número grande de procesos (O(n) cada vez que un `SIGCHLD` es recibido).

  Nuevo en la versión 3.8.

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`.

  Esta solución es tan segura como `MultiLoopChildWatcher` y tiene la misma complejidad O(n) pero requiere de un bucle de eventos ejecutándose en el hilo principal para trabajar.

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.

  No hay sobrecarga notable cuando se gestiona un número grande de procesos secundarios (O(1) cada vez que un proceso secundario termina).

  Esta solución requiere un bucle de eventos ejecutándose en el hilo principal para trabajar, como `SafeChildWatcher`.

## 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())