Conceptos de concurrencia asíncrona

La mayoría de los programas que usan otros modelos de concurrencia están escritos de manera lineal, y confían en los hilos subyacentes o en la gestión de procesos al tiempo de ejecución del lenguaje o el sistema operativo para cambiar el contexto según corresponda. Una aplicación basada en asyncio requiere que el código de la aplicación maneje explícitamente los cambios de contexto, y usar las técnicas para hacer eso correctamente depende de la comprensión de varios conceptos interrelacionados.

El marco proporcionado por asyncio se centra en un bucle de eventos un objeto de primera clase responsable de manejar eficientemente los eventos de E/S, eventos del sistema y cambios de contexto de la aplicación. Varias implementaciones del bucle se proporcionan, para aprovechar eficientemente las capacidades del sistema operativo. Mientras que un valor por defecto razonable es usualmente seleccionado automáticamente, también es posible elegir una implementación del bucle de eventos en particular desde dentro de la aplicación. Esto es útil bajo Windows, por ejemplo, donde algunas clases de bucle agregan soporte para externos procesos de una manera que puede cambiar algunas eficiencias en la E/S de red.

Una aplicación interactúa con el bucle de eventos explícitamente para registrar código a ejecutar, y permite que el bucle de eventos realice las llamadas necesarias en el código de la aplicación cuando los recursos están disponibles. Por ejemplo, un servidor en red abre los conectores y luego los registra para recibir avisos cuando eventos ocurren en ellos. El bucle de eventos alerta al código del servidor cuando hay una nueva conexión entrante o cuando hay datos para leer. Se espera que el código de la aplicación ceda el control nuevamente después de un corto período de tiempo cuando no se puede hacer más trabajo en el contexto actual. Por ejemplo, si no hay más datos para leer desde un conector el servidor debe devolver el control al bucle de eventos.

El mecanismo para devolver el control al bucle de eventos depende de las co-rutinas Python, funciones especiales que ceden el control a la llamador sin perder su estado. Las co-rutinas son similares a las funciones generador, y de hecho los generadores pueden ser utilizados para implementar co-rutinas en versiones de Python anteriores a 3.5 sin soporte nativo para objetos co-rutina. asyncio también proporciona una capa de abstracción basada en clases para protocolos y transportes para escribir código utilizando funciones de devolución de llamada en lugar de escribir directamente co-rutinas. Tanto en el modelos basados en clases y co-rutinas, cambiar explícitamente el contexto al volver a entrar al bucle de eventos reemplaza los cambios implícitos de contexto la implementación de hilos de Python.

Un futuro es una estructura de datos que representa el resultado del trabajo que aún no se ha completado. El bucle de eventos puede esperar que un objeto Future se configure como hecho, permitiendo que una parte de una aplicación esperar a que otra parte termine un trabajo. Además de futuros, asyncio incluye otras primitivas de concurrencia, tales como cerraduras y semáforos.

Una Task es una subclase de Future que sabe cómo envolver y gestionar la ejecución de una co-rutina. Las tareas pueden ser programadas con el bucle de eventos para ejecutarse cuando los recursos que necesitan estén disponibles, y para producir un resultado que pueda ser consumido por otras co-rutinas.