python - por - Torcido: hacer que el código no se bloquee
descargar archivos bloqueados gmail 2018 (1)
Estoy un poco confundido acerca de cómo escribir código asíncrono en python / twisted. Supongamos (por razones de razonamiento) que estoy exponiendo una función al mundo que tomará un número y devolverá Verdadero / Falso si es primo / no primo, por lo que se ve vagamente como esto:
def IsPrime(numberin):
for n in range(2,numberin):
if numberin % n == 0: return(False)
return(True)
(sólo para ilustrar).
Ahora digamos que hay un servidor web que necesita llamar a IsPrime basado en un valor enviado. Esto llevará mucho tiempo para un gran numberin
.
Si, mientras tanto, otro usuario solicita la primalidad de un número pequeño, ¿hay una manera de ejecutar las dos llamadas de función de forma asíncrona utilizando la arquitectura de reactor / diferidos para que el resultado del cálculo corto se devuelva antes del resultado del cálculo largo?
Entiendo cómo hacer esto si la funcionalidad de IsPrime provino de algún otro servidor web en el que mi servidor web haría un getPage diferido, pero ¿y si es solo una función local?
es decir, ¿puede Twisted compartir de alguna manera el tiempo entre las dos llamadas a IsPrime, o eso requeriría una invocación explícita de un nuevo hilo?
O, ¿sería necesario dividir el bucle IsPrime en una serie de bucles más pequeños para que el control pueda pasar al reactor rápidamente?
¿O algo mas?
Creo que su comprensión actual es básicamente correcta. Twisted es solo una biblioteca de Python y el código de Python que escribes para usarla se ejecuta normalmente, como es de esperar que el código de Python: si tienes un solo hilo (y un solo proceso), entonces solo ocurre una cosa a la vez. Casi ninguna API proporcionada por Twisted crea nuevos procesos o subprocesos, por lo que en el curso normal de las cosas, su código se ejecuta de forma secuencial; isPrime
no puede ejecutarse una segunda vez hasta que haya terminado de ejecutarse la primera vez.
Aún considerando un solo hilo (y un solo proceso), toda la "concurrencia" o el "paralelismo" de Twisted se debe al hecho de que, en lugar de bloquear la E / S de la red (y algunas otras operaciones de bloqueo), Twisted proporciona herramientas para Realizando la operación de forma no bloqueante. Esto permite que su programa continúe realizando otro trabajo cuando, de lo contrario, podría haberse atascado sin hacer nada esperando que se complete una operación de E / S de bloqueo (como leer o escribir en un socket).
Es posible hacer las cosas "asíncronas" dividiéndolas en trozos pequeños y dejando que los controladores de eventos se ejecuten entre estos trozos. Este enfoque a veces es útil, si la transformación no hace que el código sea mucho más difícil de entender y mantener. Twisted proporciona un ayudante para programar estos trozos de trabajo, cooperate
. Es beneficioso utilizar este ayudante, ya que puede tomar decisiones de programación basadas en todas las diferentes fuentes de trabajo y garantizar que quede tiempo para prestar servicio a las fuentes de eventos sin una latencia adicional significativa (en otras palabras, cuantas más tareas agregue) , menos tiempo tendrá cada trabajo, para que el reactor pueda seguir haciendo su trabajo).
Twisted también proporciona varias API para tratar con subprocesos y procesos. Estos pueden ser útiles si no es obvio cómo dividir un trabajo en partes. Puede usar twistedmatrix.com/documents/11.0.0/api/… para ejecutar una función (segura para subprocesos) en un grupo de subprocesos. Convenientemente, esta API devuelve un Deferred
que finalmente se activará con el valor de retorno de la función (o con un Failure
si la función genera una excepción). Estos aplazados se parecen a cualquier otro, y en lo que respecta al código que los utiliza, también podría volver de una llamada como getPage
, una función que no utiliza subprocesos adicionales, solo E / S sin bloqueo y controladores de eventos.
Dado que Python no es ideal para ejecutar múltiples subprocesos vinculados a la CPU en un solo proceso, Twisted también proporciona una API sin bloqueo para iniciar y comunicarse con procesos secundarios. Puede descargar cálculos de dichos procesos para aprovechar las CPU o núcleos adicionales sin preocuparse de que la GIL lo ralentice, algo que ni la estrategia de fragmentación ni el enfoque de subprocesamiento ofrecen. La API de nivel más bajo para tratar con tales procesos es twistedmatrix.com/documents/current/core/howto/process.html . También está Ampoule , un paquete que gestionará un grupo de procesos para usted y proporciona un análogo a deferToThread
para procesos, deferToAMPProcess
.