IO asíncrona de Python: API

IO asíncrona de Python: API


El asyncio de Python es una biblioteca estándar para escribir código concurrente usando la sintaxis async / await. A través de la explicación en la sección anterior, aprendimos sobre su historia cambiante. En la última versión de Python 3.7, asyncio ha hecho un gran ajuste. La API de esta biblioteca se divide en API de alto nivel y API de bajo nivel, e introduce métodos avanzados como asyncio.run () para hacer que los programas asíncronos sean más Conciso
Esta sección espera delinear la última versión 3.7 de asnycio; primero, comprenda la biblioteca de IO asíncrona de Python desde lo global.

La API de alto nivel de Asyncio mejora principalmente los siguientes aspectos:
  • Ejecute Python coroutines simultáneamente y controle completamente su proceso de ejecución;
  • Ejecutar red IO e IPC;
  • Controlar el proceso hijo;
  • Implementar tareas distribuidas a través de colas;
  • Sincronizar código concurrente.
La API de bajo nivel de Asyncio se usa para apoyar el desarrollo de marcos y marcos asíncronos:
  • Cree y administre bucles de eventos, proporcione API asíncronas para la red, ejecute procesos secundarios, procese señales del sistema operativo, etc.
  • Implementar protocolos de alta eficiencia a través de transportes;
  • Bibliotecas y código basados ​​en devolución de llamada a través del puente de sintaxis async / await.

Asyncio API avanzada

Las API de alto nivel nos facilitan la escritura de aplicaciones basadas en asyncio. Estas API incluyen:

(1) Coroutines y tareas.

La rutina se declara con la sintaxis async / await y es la forma recomendada de escribir aplicaciones asíncronas. El historial @asyncio.coroutine y el yield from han sido desaprobados y están programados para eliminarse en Python 3.10.asyncio.run(coro, *, debug=False) se puede ejecutar a través de la función asyncio.run(coro, *, debug=False) , que administra el bucle de eventos y finaliza el generador asíncrono. Debe utilizarse como el punto de entrada principal para el programa de asyncio, equivalente a la función principal, que solo debe llamarse una vez.
Las tareas se utilizan para la planificación simultánea de las rutinas y se pueden usar para rastreadores web simultáneos. Usando asyncio.create_task() puede empaquetar una rutina en una tarea, que se programa automáticamente para ejecutarse muy rápidamente.
Coroutines, tareas y futuros son todos objetos que se pueden esperar. Entre ellos, el Futuro es un objeto que se puede esperar de bajo nivel, que representa el resultado final de una operación asíncrona.

(2) flujo

Las secuencias son primitivas de alto nivel que utilizan async / await para conexiones de red. Las transmisiones permiten que los datos se envíen y reciban sin el uso de devoluciones de llamada o protocolos y transportes de bajo nivel. La lectura y escritura asíncronas TCP tiene la función de cliente asyncio.open_connection() y la función de servidor asyncio.start_server() . También admite Unix Sockets: asyncio.open_unix_connection() y asyncio.start_unix_server() .

(3) Primitiva de sincronización.

El diseño de la primitiva de sincronización de asyncio es similar a la primitiva del módulo de subprocesamiento. Hay dos consideraciones importantes:
Las primitivas asyncio no son seguras para subprocesos, por lo que no deben utilizarse para la sincronización de subprocesos del sistema operativo (pero con subprocesos)
Los métodos de estas primitivas de sincronización no aceptan parámetros de tiempo de espera, use la función asyncio.wait_for() para realizar operaciones de tiempo de espera.
Asyncio tiene las siguientes primitivas básicas de sincronización:
  • Bloqueo
  • Evento
  • Condicion
  • Semáforo
  • BoundedSemaphore

(4) Proceso del niño.

Asyncio proporciona API para crear y administrar procesos secundarios a través de async / await. A diferencia del subproceso de la biblioteca estándar de Python, las funciones del proceso hijo de asyncio son asíncronas y proporcionan una variedad de herramientas para manejar estas funciones, lo que facilita la ejecución y el monitoreo de varios procesos hijos en paralelo. Hay dos formas principales de crear un proceso hijo:
coroutine asyncio.create_subprocess_exec()
coroutine asyncio.create_subprocess_shell()

(5) Queue

El diseño de la cola de asyncio es similar a la clase de la cola del módulo estándar.Aunque las colas de asyncio no son seguras para subprocesos, están diseñadas para ser utilizadas exclusivamente para el código async / await. Tenga en cuenta que el método de cola de asyncio no tiene un parámetro de tiempo de espera, use la función asyncio.wait_for() para realizar una operación de cola de tiempo de espera.
Debido a que es similar al diseño de clase de la cola del módulo de anotación, no hay mucha diferencia entre el uso y la cola. Simplemente agregue aguardar delante de la función correspondiente. La cola de asyncio proporciona tres colas diferentes:
  • Clase asyncio.Queue cola FIFO
  • Clase de cola de prioridad asyncio.PriorityQueue
  • Class asyncio.LifoQueue Último en la primera cola de salida

(6) Anormal

Asyncio proporciona varias excepciones, son:
  • TimeoutError,
  • Error cancelado,
  • InvalidStateError,
  • SendfileNotAvailableError
  • IncompleteReadError
  • LimitOverrunError

Asyncio API de bajo nivel

Las API de bajo nivel proporcionan soporte para escribir bibliotecas y marcos basados ​​en asyncio, y aquellos interesados ​​en escribir bibliotecas y marcos asíncronos deben estar familiarizados con estas API de bajo nivel. Principalmente incluyen:

(1) bucle de eventos

El bucle de eventos es el núcleo de cada aplicación de asyncio. El bucle de eventos ejecuta tareas asíncronas y devoluciones de llamada, realiza operaciones de E / S de red y ejecuta procesos secundarios.
Los desarrolladores de aplicaciones generalmente deben usar funciones asíncronas avanzadas, como asyncio.run() , y rara vez necesitan hacer referencia a objetos de bucle o llamar a sus métodos.
La función asyncio.get_running_loop() se ha agregado a Python 3.7.

(2) Futuros

El objeto Future se usa para unir código de bajo nivel basado en devolución de llamada con código async / await de alto nivel.
El futuro representa el resultado final de una operación asíncrona. No hilo seguro.
El futuro es un objeto waitable. Coroutines puede esperar a los objetos futuros hasta que tengan un resultado o un conjunto de excepciones, o hasta que se cancelen.
Por lo general, los futuros se utilizan para habilitar el código basado en devolución de llamada de bajo nivel (por ejemplo, en los protocolos implementados utilizando el transporte asyncio) para interoperar con el código asincrónico / de espera de alto nivel.

(3) Transmisión y Protocolo (Transportes y Protocolos)

El transporte y el protocolo son utilizados por los bucles de eventos de bajo nivel, como la función loop.create_connection() . Utilizan un estilo de programación basado en la devolución de llamada y admiten implementaciones de alto rendimiento de protocolos de red o IPC, como HTTP.
En el nivel más alto, la transmisión implica la transmisión de bytes, y el protocolo determina qué bytes se transfieren (en cierta medida).
En otras palabras, el transporte es una abstracción de un socket (o un punto final de E / S similar), y el protocolo es una abstracción de la aplicación desde una perspectiva de transporte.
Otro punto de vista es que las interfaces de transporte y protocolo definen juntas una interfaz abstracta que utiliza la E / S de red y la E / S interproceso.
Siempre hay una relación 1: 1 entre el transporte y los objetos de protocolo: el protocolo llama al método de transporte para enviar datos, y el método de protocolo de llamada de transporte pasa los datos recibidos.
La mayoría de los métodos de bucle de eventos orientados a la conexión (como loop.create_connection() ) generalmente aceptan el parámetro protocol_factory, que se usa para crear un objeto Protocol para la conexión aceptada, representado por el objeto Transport. Estos métodos suelen devolver tuplas (transporte, protocolo).

(4) Política (Policy)

La estrategia de bucle de eventos es un objeto global que se divide por proceso y se usa para controlar la administración de los bucles de eventos. Cada ciclo de eventos tiene una política predeterminada que se puede cambiar y personalizar mediante la API de políticas.
Una política define el concepto de contexto y administra los bucles de eventos individuales según el contexto. La política predeterminada define el contexto como el hilo actual.
El comportamiento de las get_event_loop() , set_event_loop() y new_event_loop() se puede personalizar utilizando una estrategia de bucle de eventos personalizada.

(5) Soporte de plataforma

El módulo asyncio está diseñado para ser portátil, pero debido a la arquitectura subyacente y la funcionalidad de la plataforma, existen algunas diferencias y limitaciones sutiles en algunas plataformas. En la plataforma Windows, algunos no son compatibles, como loop.create_unix_connection() y loop.create_unix_server() . Linux y los macOS más nuevos son todos compatibles.

Resumen

Python 3.7 aclara su arquitectura al agrupar asyncio. Las aplicaciones que escriben IO asíncronas solo necesitan estar familiarizadas con las API de alto nivel. Debe comprender las API de bajo nivel cuando necesita escribir bibliotecas y marcos para IO asíncronas.

留言