2015-08-06 5 views
21

Ich schreibe eine Anwendung in Flask, die wirklich gut funktioniert, außer dass WSGI ist synchron und blockiert. Ich habe insbesondere eine Aufgabe, die zu einer API eines Drittanbieters aufruft, und diese Aufgabe kann einige Minuten dauern. Ich möchte diesen Anruf (es ist eigentlich eine Reihe von Anrufen) machen und es laufen lassen. während die Kontrolle an Flask zurückgegeben wird.Erstellen einer asynchronen Task in Flask

Meine Ansicht wie folgt aussieht:

@app.route('/render/<id>', methods=['POST']) 
def render_script(id=None): 
    ... 
    data = json.loads(request.data) 
    text_list = data.get('text_list') 
    final_file = audio_class.render_audio(data=text_list) 
    # do stuff 
    return Response(
     mimetype='application/json', 
     status=200 
    ) 

Nun, was ich tun möchte, ist die

final_file = audio_class.render_audio() 

Laufleitung und einen Rückruf bieten ausgeführt wird, wenn das Verfahren kehrt werden, während Flask können Anfragen weiter bearbeiten Dies ist die einzige Aufgabe, die Flask asynchron ausführen muss, und ich hätte gerne einen Ratschlag, wie dies am besten umgesetzt werden kann. Ich habe mir Twisted und Klein angeschaut, aber ich bin mir nicht sicher, dass sie übertrieben sind, da vielleicht Threading ausreichen würde.

Jeder Rat würde sehr geschätzt werden.

EDIT

Oder Vielleicht Celery ist eine gute Wahl für das?

+0

Normalerweise verwende ich Sellerie für diese ... es könnte Overkill sein, aber afaik Threading funktioniert nicht gut in Web-Umgebungen (Iirc ...) –

+0

Richtig. Ja - ich habe gerade Sellerie untersucht. Es könnte ein guter Ansatz sein. Einfach mit Flask zu implementieren? –

+0

heh ich neige dazu, einen Socket-Server auch zu benutzen (flask-socketio) und ja, ich dachte, es war ziemlich einfach ... der schwierigste Teil war, alles zu installieren –

Antwort

24

Ich würde Celery verwenden, um die asynchrone Aufgabe für Sie zu behandeln. Sie müssen einen Broker installieren, der als Aufgabenwarteschlange dient (RabbitMQ und Redis werden empfohlen).

app.py:

from flask import Flask 
from celery import Celery 

broker_url = 'amqp://[email protected]'   # Broker URL for RabbitMQ task queue 

app = Flask(__name__)  
celery = Celery(app.name, broker=broker_url) 
celery.config_from_object('celeryconfig')  # Your celery configurations in a celeryconfig.py 

@celery.task(bind=True) 
def some_long_task(self, x, y): 
    # Do some long task 
    ... 

@app.route('/render/<id>', methods=['POST']) 
def render_script(id=None): 
    ... 
    data = json.loads(request.data) 
    text_list = data.get('text_list') 
    final_file = audio_class.render_audio(data=text_list) 
    some_long_task.delay(x, y)     # Call your async task and pass whatever necessary variables 
    return Response(
     mimetype='application/json', 
     status=200 
    ) 

Führen Sie Ihre Flask App, und einen anderen Prozess starten Sie Ihren Sellerie Arbeiter laufen.

$ celery worker -A app.celery --loglevel=debug 

ich auch Miguel Gringberg der write up für eine mehr in die Tiefe Anleitung zur Verwendung von Sellerie mit Flask beziehen würde.

+0

Ja, das sieht nach dem Weg aus. Vielen Dank! Und danke für das Code-Snippet. –

-3

Ich schlage eine Änderung in der Architektur vor. Ich würde ZeroRPC zusammen mit RESTFul Interface Fassade verwenden.

+6

Warum ist ZeroRPC besser als Kolben? – shrewmouse

Verwandte Themen