2012-09-07 13 views
6

Tengo que trabajar mucho en mi aplicación Flask. Y quiero hacerlo asincrónico. Simplemente comienza a trabajar y luego verifica el estado desde javascript.Flask long routines

que estoy tratando de hacer algo como:

@app.route('/sync') 
def sync(): 
    p = Process(target=routine, args=('abc',)) 
    p.start() 

    return "Working..." 

Pero esto crea trabajadores gunicorn difuntos.

¿Cómo se puede resolver? ¿Debería usar algo como apio?

Respuesta

11

Hay muchas opciones. Puede desarrollar su propia solución, usar apio o trenzado (estoy seguro de que hay más opciones ya hechas, pero esas son las más comunes).

Desarrollar su solución interna no es difícil. Se puede utilizar el módulo de multiprocessing de la biblioteca estándar de Python:

  • Cuando llega una tarea de insertar una fila en la base de datos con el ID de la tarea y el estado.
  • A continuación, inicie un proceso para realizar el trabajo que actualiza el estado de la fila al finalizar.
  • Puede tener una vista para verificar si la tarea está terminada, lo que realmente solo verifica el estado en el correspondiente.

Por supuesto, debe pensar dónde desea almacenar el resultado del cálculo y qué ocurre con los errores.

Ir con apio también es fácil. Se vería como el siguiente. Para definir una función a ejecutar de forma asincrónica:

@celery.task 
def mytask(data): 

    ... do a lot of work ... 

Entonces, en lugar de llamar a la tarea directamente, como mytask(data), lo que ejecutarlo de inmediato, utilice el delay método:

result = mytask.delay(mydata) 

Por último, puede comprobar si el resultado está disponible o no con ready:

result.ready() 

sin embargo, remembe Para que use Aplery, debe ejecutar un proceso externo worker.

No he mirado Twisted, así que no puedo decir si es más o menos complejo que esto (pero debería estar bien hacer lo que quieras hacer también).

En cualquier caso, cualquiera de esas soluciones debería funcionar bien con Flask. Para comprobar el resultado, no importa en todo si utiliza Javascript. Simplemente haga que la vista que verifica el estado devuelva JSON (puede usar Flask's jsonify).

+0

Bueno, realmente tengo todo lo que dijo sobre el almacenamiento de resultados en DB. El principal problema con la implementación de mi propia solución es que cuando estoy usando 'multiprocesamiento 'hace que el trabajador de gunicornio se extinga. – sashab

+0

Vaya, lamento haber leído mal su pregunta. Parece que su problema es que su proceso principal finaliza después de la declaración de devolución, que efectivamente elimina el proceso secundario que acaba de crear. Para evitar eso, solo tiene que demonizar al niño antes de que el padre salga (es decir, separarlo) [python-daemon] (http://pypi.python.org/pypi/python-daemon/) – pacha

+0

Me sale 'ValueError: I/O operación en archivo cerrado' cuando se usa con multiprocesamiento. Parece que necesito usar Popen. Establecer 'Process(). Daemon = True' tampoco ayuda. – sashab

2

Usaría un intermediario de mensajes como rabbitmq o activemq. El proceso del matraz agregaría trabajos a la cola de mensajes y un proceso de trabajo de larga ejecución (o procesos de grupo o de trabajo) eliminaría trabajos de la cola para completarlos. El proceso de trabajo podría actualizar una base de datos para permitir que el servidor de matraz conozca el estado actual del trabajo y pasar esta información a los clientes.

El uso del apio parece ser una buena forma de hacerlo.