Servir la solicitud web en pitón que genera un nuevo subproceso de larga duración

Actualmente tengo una aplicación de línea de comando python que utiliza python invoke paquete para organizar, listar y ejecutar tareas. Hay muchos archivos de tarea (controlados " creados por usuarios, no yo). El tiempo de ejecución para algunos archivos de tareas puede ser más de una hora. Cada tarea es en realidad un script de prueba/programa. invoke es útil en la lista/ejecución de todas las tareas en un archivo de tarea (lo llamamos un testsuite) o sólo un montón de ellos (una tarea colección) o una sola tarea. (Tener una tonelada de scripts sueltos y organizar, enumerar " ejecutarlos en la forma que los usuarios quieren sería una tarea bastante, por lo tanto invoke). Sin embargo, invoke no se puede utilizar como biblioteca. No ofrece una API que se puede aprovechar para enumerar y ejecutar tareas de prueba. Así que estoy obligado a correr invoke como comando shell en subprocess del programa de línea de comandos. Sustituyo (vía) execl()) el proceso actual con invoke porque una vez que el control pasa invoke, no hay necesidad de volver al proceso padre. Muy bien ..

Ahora, hay un requisito de que este programa de línea de comandos sea llamada desde una aplicación web. Así que necesito envolver este programa cmdline en una API http restante. He decidido usar bottle.py para mantener las cosas simples.

Entiendo que el testsuite de larga duración (tareas) tendrá que hacerse fuera del ciclo de solicitud/respuesta http. Pero no puedo concluir exactamente cómo hacerlo (prob. Puede que esté exagerando). Pero esto es lo que quiero...

  • Las tareas son escritas por los usuarios. Siempre son sincronizados, pueden sleep o ejecutar comandos de shell vía subprocess.run().
  • La aplicación es interna, no será bombardeada con un gran número de solicitudes. No de usuarios Max. 10.
  • Pero cada solicitud (de tipo que carreras la tarea) tomará minutos y algunos casos > hora para completar. Las nuevas solicitudes durante esto no deben bloquear.
  • La solicitud de llamada (que se ejecuta en un host diferente) tendrá que reportar el progreso de la tarea en ejecución al navegador UI. ('progress bar')
  • Capacidad de comunicarse con la tarea de ejecución y 'cancel' desde el navegador UI.

Con la situación anterior, soy correcto en decir ..

  • porque un nuevo 'proceso' debe ser desperdiciado subprocess y excl en el código actual) para una solicitud, que descarta usar 'panes' de cualquier tipo (os hilos, greenlets, gevent)?
  • Utilizar cualquier biblioteca asinc ( framework web/http server o en código de aplicación) no será de mucha ayuda, porque cada Corre la solicitud tendrá que ser un nuevo proceso de todos modos?
  • ¿Cómo se desperdiciará el proceso cuando llegue una solicitud? Dejar el servidor web/htpp (gunicorn?) ¿Sí? o ¿Mi solicitud tiene que tomar caso de forjarse?
  • ¿Es 'gunicorn' una buena opción para esta situación?
  • Tengo la sensación de que los usuarios también pueden pedir la capacidad de Calendario tareas/pruebas. Podría terminar usando algún tipo de task queue. He leído 'huey' y siento que es ligero' simple para mis necesidades. (No redis/Celery). Pero cualquier cola de tarea también significa un proceso de consumo separado para administrar? Más partes móviles a la mezcla.
  • 'progress-bar' funcionalidad significa, subproceso tiene que seguir actualizando su progreso en algún lugar y llamar a la aplicación tiene que leer desde allí. ¿Esto necesita 'tarea de latas'?

Hay un montón de material en todo esto y he leído bastante algunos si. Pero todavía me ha dejado poco claro cómo ir exactamente a implementar mis requisitos. Cualquier dirección/puntos sería apreciado. También apreciaría cualquier consejo sobre lo que 'no usar'.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por byteninja8245


3 Respuestas:

  • Si necesitas algo realmente simple entonces podrías escribir un envoltorio alrededor de la unidad de tareas (herramienta Linux para ejecutar tareas) https://vicerveza.homeunix.net/~viric/soft/ts/ (especialmente https://vicerveza.homeunix.net/~viric/soft/ts/article_linux_com.html para más detalles)

    De lo contrario, probablemente sea mejor cambiar a uwsgi spooler, rq con redis o apio con con conejomq (porque con redis funciona en cierta medida).

    Respondida el Dec 18, 2020 a las 07:07 - por codeartisan

    Votos positivos: 0 | Votos negativos: 0

  • Para implementar un servicio web en Python que genere un nuevo subproceso de larga duración, puedes seguir los siguientes pasos y consideraciones:

    • Utiliza el framework web Bottle para crear la API REST que envuelva tu programa de línea de comandos.
    • Para ejecutar las tareas largas de forma asincrónica, puedes usar el módulo `subprocess` de Python para crear subprocesos que ejecuten las tareas de forma independiente.
    • Para manejar la comunicación con los subprocesos y reportar el progreso al navegador, puedes implementar un mecanismo de comunicación en tiempo real utilizando WebSockets o Server-Sent Events en Bottle.
    • Para administrar la concurrencia y evitar bloqueos cuando se ejecutan múltiples tareas largas, considera utilizar un servidor web como Gunicorn que maneje múltiples solicitudes de forma concurrente.
    • Si los usuarios también pueden programar tareas, podrías considerar la integración de una cola de tareas como Huey para gestionar la ejecución de tareas programadas de manera diferida y así liberar recursos del servidor principal.
    • Para la funcionalidad de la barra de progreso, puedes implementar un mecanismo en el backend que actualice el progreso de la tarea en una base de datos o memoria compartida, y que la interfaz de usuario obtenga esa información a través de peticiones AJAX.

    En resumen, puedes utilizar subprocesos para ejecutar tareas largas, comunicarte con ellos de forma asincrónica a través de Flask, manejar la concurrencia con un servidor web como Gunicorn, y gestionar tareas programadas con una cola de tareas como Huey. Para la funcionalidad de la barra de progreso, puedes implementar un mecanismo de actualización periódica de la interfaz de usuario utilizando tecnologías web como WebSockets o Server-Sent Events. ¡Espero que esta información te ayude a implementar tu aplicación de manera efectiva!

    Respondida el Dec 19, 2020 a las 07:07 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Uso de subprocesos para tareas de larga duración:

    Es correcto utilizar subprocesos para ejecutar tareas de larga duración, ya que permiten que el proceso principal continúe ejecutándose mientras las tareas se ejecutan en segundo plano.

    Uso de bibliotecas asíncronas:

    En este caso, las bibliotecas asíncronas no serían útiles ya que cada solicitud requiere un nuevo proceso. La asincronía se utiliza principalmente para manejar múltiples solicitudes simultáneamente dentro de un solo proceso.

    Manejo de procesos cuando llega una solicitud:

    Cuando llega una nueva solicitud, puede manejar el proceso de la siguiente manera:

    • Cree un nuevo subproceso para ejecutar la tarea.
    • Almacene el proceso en alguna estructura de datos para facilitar el seguimiento y la comunicación.
    • Responda a la solicitud con un estado de "tarea en ejecución" y un identificador único para la tarea.

    Uso de Gunicorn:

    Gunicorn puede ser una buena opción para esta situación. Es un servidor HTTP de Python que admite procesos de trabajo múltiples y autoactualizables. Esto garantiza que las solicitudes se distribuyan entre múltiples procesos, evitando bloqueos.

    Funcionalidad de la "barra de progreso":

    Para implementar la funcionalidad de la barra de progreso, puede hacer que el subproceso escriba actualizaciones de progreso en un archivo compartido o una cola de mensajes. La aplicación principal puede leer desde esta fuente para actualizar la barra de progreso en el navegador.

    Programación de tareas:

    Si necesita la capacidad de programar tareas, puede utilizar una cola de tareas como Celery. Sin embargo, esto requerirá un proceso de consumo separado para administrar la cola y ejecutar las tareas programadas.

    Recomendaciones sobre lo que no usar:

    Hilos: Los hilos pueden no ser adecuados para ejecutar tareas de larga duración, ya que comparten el mismo espacio de memoria con el proceso principal y pueden bloquearse. Greenlets: Greenlets son similares a los hilos, pero tampoco son adecuados para tareas de larga duración. Gevent:* Gevent es un marco de concurrencia que permite la ejecución asincrónica dentro de un solo proceso. Sin embargo, no sería útil en este caso porque cada solicitud requiere un nuevo proceso.

    Respondida el Dec 19, 2020 a las 07:22 - por Gemini

    Votos positivos: 0 | Votos negativos: 0