Red de conocimiento informático - Problemas con los teléfonos móviles - Cómo utilizar el paquete asyncio para el procesamiento concurrente de Python

Cómo utilizar el paquete asyncio para el procesamiento concurrente de Python

Esta vez le mostraré cómo usar el paquete asyncio de procesamiento concurrente de Python y cuáles son las precauciones al usar el paquete asyncio de procesamiento concurrente de Python. El siguiente es un caso práctico, echemos un vistazo.

Introducción: este artículo registra mis conocimientos clave y mi experiencia personal en el aprendizaje de los conceptos básicos del flujo de control de Python. Los amigos que planeen comenzar con Python pueden venir, aprender y comunicarse juntos.

Puntos clave de este artículo:

1. Comprender las funciones y el uso del paquete asyncio

2. p>

3. Aprenda a usar corrutinas para evitar el infierno de las devoluciones de llamadas.

1. Utilice el paquete asyncio para programación concurrente

1. Concurrencia y paralelismo

Concurrencia: procese varias cosas a la vez.

Paralelo: Hacer varias cosas a la vez.

La concurrencia se utiliza para formular soluciones para resolver problemas que pueden (pero no necesariamente) ser paralelos. La concurrencia es mejor.

2. Descripción general de asyncio

Comprenda las 4 características de asyncio:

El paquete asyncio utiliza rutinas controladas por bucles de eventos para lograr concurrencia.

Las rutinas adecuadas para la API asyncio deben usar el rendimiento en el cuerpo de la definición, pero no pueden usar el rendimiento.

Las corrutinas procesadas con asyncio deben estar decoradas con @asyncio.coroutine en el cuerpo de la definición. La función de la decoración es resaltar la corrutina. Al mismo tiempo, cuando la corrutina no produce valor, la corrutina se recolectará como basura.

Desde Python 3.4, el paquete asyncio solo admite directamente los protocolos TCP y UDP. Si desea utilizar asyncio para implementar clientes y servidores HTTP, a menudo se utiliza aioplete(). Es decir, la corrutina no se controla llamando a la función next() o al método .send().

La cadena de rutina escrita finalmente delega responsabilidades a una función de rutina o método de rutina en el paquete asyncio a través de rendimiento de. Es decir, el subgenerador más interno es la función en la biblioteca que realmente realiza operaciones de E/S, no la función que escribimos nosotros mismos.

Ejemplo: animar un puntero giratorio textual mediante el paquete asyncio y la corrutina:

importar asyncio

importar itertools

importar sistema

@asyncio.coroutine # La corrutina entregada a asyncio debe estar decorada con @asyncio.coroutine

def spin(msg):

for char in itertools.cycle(' |/-\'):

status = char ' ' msg

print(status)

prueba:

rendimiento de asyncio .sleep(.1) # Utilice el rendimiento de asyncio.sleep(.1) en lugar de time.sleep(.1). Dicho sueño no bloqueará el bucle de eventos.

excepto asyncio.CancelledError: # Si la función de giro genera una excepción asyncio.CancelledError después de activarse, el motivo es que se emitió una solicitud de cancelación, por lo que el bucle sale.

break

@asyncio.coroutine

def slow_function(): # La función slow_function es una corrutina cuando se utiliza la suspensión para pretender realizar operaciones de E/S. , utilice el rendimiento de la ejecución continua del bucle de eventos.

# Finge esperar E/S durante un período de tiempo

rendimiento de asyncio.sleep(3) # rendimiento de asyncio.sleep(3) La expresión da control al bucle principal, en Reanudar esta rutina después de dormir.

return 42

@asyncio.coroutine

def supervisor(): # La función de supervisor también es una corrutina

spinner = asyncio .async (spin('thinking!')) # asyncio.async(...) la función programa el tiempo de ejecución de la rutina de giro, utiliza un objeto Task para ajustar la rutina de giro y regresa inmediatamente.

print('spinner object: ', spinner)

resultado = rendimiento de slow_function() # Controla la función slow_function(). Después de terminar, obtenga el valor de retorno.

# Mientras tanto, el bucle de eventos continúa ejecutándose porque la función slow_function finalmente devuelve el control al bucle principal utilizando el rendimiento de la expresión asyncio.sleep(3).

spinner.cancel() # El objeto Tarea se puede cancelar; después de la cancelación, se generará una excepción asyncio.CancelledError en el rendimiento donde la rutina está actualmente en pausa. La corrutina puede detectar esta excepción, retrasar la cancelación o incluso rechazar la cancelación.

devolver resultado

if name == 'main':

loop = asyncio.get_event_loop() # Obtener una referencia al bucle de eventos

resultado = loop.run_until_complete(supervisor()) # Impulsa la rutina supervisora ​​y deja que se ejecute hasta su finalización. El valor de retorno de esta rutina es el valor de retorno de esta llamada.

loop.close()

print('Respuesta:', resultado) 3. Comparación entre subprocesos y corrutinas

Subprocesos: El programador está activo en cualquier tiempo Puede interrumpir hilos. Hay que recordar conservar la cerradura. Proteja partes importantes del programa para evitar que las operaciones de varios pasos se interrumpan durante la ejecución y que los datos queden en un estado no válido.

Coroutine: Se proporcionará protección integral de forma predeterminada para evitar interrupciones. No es necesario conservar bloqueos para las corrutinas. Cuando las operaciones se sincronizan entre varios subprocesos, las propias corrutinas se sincronizarán porque solo se ejecuta una corrutina en cualquier momento.

4. Rendimiento de elementos, tareas y corrutinas

En el paquete asyncio, los elementos y las corrutinas están estrechamente relacionados, porque puedes usar el rendimiento de asyncio. Los objetos futuros producen resultados. Esto significa que si foo es una función de rutina o una función ordinaria que devuelve una instancia de Futuro o Tarea, puedes escribir: res=yield desde foo(). Esta es una de las razones por las que las corrutinas y los futuros se pueden intercambiar en muchos lugares del paquete asyncio.

2. Evite bloquear llamadas

1. Hay dos formas de evitar que el bloqueo de llamadas termine todo el proceso de solicitud:

En un hilo separado, ejecute varios bloqueos. operaciones.

Convierta cada operación de bloqueo en una llamada asincrónica sin bloqueo.

El uso de subprocesos múltiples para manejar una gran cantidad de conexiones consumirá demasiada memoria, por lo que las devoluciones de llamada generalmente se usan para implementar llamadas asincrónicas.

2. Utilice el objeto Ejecutor para evitar el bloqueo del bucle de eventos:

Utilice loop.run_in_executor para delegar trabajos bloqueados (como guardar archivos) al grupo de subprocesos.

@asyncio.coroutine

def download_one(cc, base_url, semaphore, verbose):

prueba:

con (rendimiento de semáforo):

imagen = rendimiento de get_flag(base_url, cc)

excepto web.HTTPNotFound:

estado = HTTPStatus.not_found

msg = 'no encontrado'

excepto excepción como exc:

generar FetchError(cc) desde exc

else:

bucle = asyncio.get_event_loop() # Obtener una referencia al objeto del bucle de eventos

loop.run_in_executor(Ninguno, # Ninguno Usar la instancia predeterminada de TrreadPoolExecutor

save_flag, image, cc.lower( ) ' .gif') # Pasar el objeto invocable

status = HTTPStatus.ok

msg = 'OK'

si es detallado y msg:

print(cc, msg)

return Result(status, cc) El bucle de eventos de Asyncio mantiene un objeto ThreadPoolExecutor detrás de él. Podemos llamar al método run_in_executor y enviarle el objeto invocable para su ejecución. .

3. De devoluciones de llamada a elementos y corrutinas

Infierno de devolución de llamada: si una operación necesita depender de los resultados de operaciones anteriores, las devoluciones de llamada deben estar anidadas.

Infierno de devolución de llamada en Python:

def etapa1(respuesta1):

solicitud2 = paso1(respuesta1)

api_call2(solicitud2, etapa2 )

def etapa2(respuesta2):

solicitud3 = paso2(respuesta2)

api_call3(solicitud3, etapa3)

def etapa3 ( respuesta3):

paso3 (respuesta3)

api_call1 (solicitud1, paso1) usa corrutinas y rendimiento de estructuras para programación asincrónica sin usar devoluciones de llamada:

@asyncio. corrutina

def three_stages(solicitud1):

respuesta1 = rendimiento de api_call1()

solicitud2 = paso1(respuesta1)

respuesta2 = rendimiento de api_call2(solicitud2)

solicitud3 = paso2(respuesta2)

respuesta3 = rendimiento de api_call3(solicitud3)

paso3(respuesta3)

loop.create_task(tres_etapas(request1))

# La corrutina no se puede llamar directamente. El bucle de eventos debe usarse para mostrar el tiempo de ejecución de la corrutina especificada o en otras corrutinas con tiempos de ejecución programados. Utilice la expresión rendimiento de en el proceso para activarlo 4. Utilice el paquete asyncio para escribir servidores

Utilice el paquete asyncio para implementar servidores TCP y HTTP

Los servicios web se convertirán en un. Escenario de uso importante del paquete asyncio.

Creo que domina el método después de leer el caso de este artículo. Para obtener más información interesante, preste atención a otros artículos relacionados en Gxl.com.

Lectura recomendada:

Cómo convertir una cadena de Python en una matriz bidimensional

Cómo usar Vue para exportar funciones de tablas de Excel