Die Berichterstellung ergab Ergebnisse einer lang andauernden Sellerie-Aufgabe
Ich habe eine lang laufende Aufgabe in logische Unteraufgaben unterteilt, damit ich die Ergebnisse jeder Unteraufgabe nach Abschluss der Aufgabe protokollieren kann. Ich versuche jedoch, die Ergebnisse einer Aufgabe zu melden, die effektiv nie abgeschlossen wird (stattdessen ergebe ich Werte, wie es geht), und habe Mühe, dies mit meiner vorhandenen Lösung zu tun.
HintergrundIch erstelle ein Webinterface für einige Python-Programme, die ich geschrieben habe. Benutzer können Aufträge über Webformulare senden und anschließend den Fortschritt des Auftrags erneut überprüfen.
Angenommen, ich habe zwei Funktionen, auf die jeweils über separate Formulare zugegriffen wird:
med_func
: Die Ausführung dauert ca. 1 Minute. Die Ergebnisse werden an weitergeleitetrender()
, die zusätzliche Daten erzeugt.long_func
: Gibt einen Generator zurück. Jederyield
dauert in der Größenordnung von 30 Minuten und sollte dem Benutzer gemeldet werden. Es gibt so viele Ausbeuten, dass wir diesen Iterator als unendlich betrachten könnenwiderrufen).Code, aktuelle ImplementierungMitmed_func
Ich berichte Ergebnisse wie folgt:
Beim Absenden des Formulars speichere ich einAsyncResult
zu einemDjango-Sitzung:
task_result = med_func.apply_async([form], link=render.s())
request.session["task_result"] = task_result
Die Django-Ansicht für die Ergebnisseite greift darauf zuAsyncResult
. Nach Abschluss einer Aufgabe werden die Ergebnisse in einem Objekt gespeichert, das als Kontext an eine Django-Vorlage übergeben wird.
def results(request):
""" Serve (possibly incomplete) results of a session's latest run. """
session = request.session
try: # Load most recent task
task_result = session["task_result"]
except KeyError: # Already cleared, or doesn't exist
if "results" not in session:
session["status"] = "No job submitted"
else: # Extract data from Asynchronous Tasks
session["status"] = task_result.status
if task_result.ready():
session["results"] = task_result.get()
render_task = task_result.children[0]
# Decorate with rendering results
session["render_status"] = render_task.status
if render_task.ready():
session["results"].render_output = render_task.get()
del(request.session["task_result"]) # Don't need any more
return render_to_response('results.html', request.session)
Diese Lösung funktioniert nur, wenn die Funktion tatsächlich funktioniertbeendet. Ich kann logische Teilaufgaben von nicht verkettenlong_func
, weil es eine unbekannte Anzahl vonyield
s (jede Iteration vonlong_func
Die Schleife von erzeugt möglicherweise kein Ergebnis.
Gibt es eine sinnvolle Möglichkeit, auf die erhaltenen Objekte einer extrem lang laufenden Sellerie-Aufgabe zuzugreifen, damit sie angezeigt werden können, bevor der Generator erschöpft ist?