Wie man Daten von einer CherryPy BackgroundTask zurückgibt, die so schnell wie möglich läuft

Ich baue einen Web-Service für die iterative Batch-Verarbeitung von Daten mit CherryPy. Der ideale Workflow ist wie folgt:

  1. Benutzer POST-Daten an den Dienst für die Verarbeitung
  2. Wenn der Bearbeitungsauftrag frei ist, sammelt er die in der Warteschlange befindlichen Daten und startet eine weitere Iteration
  3. Während der Auftrag verarbeitet wird, verteilen die Benutzer mehr Daten an die Warteschlange für die nächste Iteration
  4. Sobald die aktuelle Iteration beendet ist, werden die Ergebnisse zurückgegeben, so dass Benutzer sie mit der gleichen API erhalten können.
  5. Der Job startet mit der nächsten Charge der in der Warteschlange befindlichen Daten.

Die zentrale Betrachtung hierbei ist, dass die Verarbeitung so schnell wie möglich mit jeder Iteration ablaufen sollte, sobald die vorherige beendet ist, unabhängig von der Datenmenge in der Warteschlange. Es gibt keine Obergrenze, wie lange jede Iteration so nehmen kann, dass ich keinen festen Zeitplan dafür erstellen kann.

  • Python: deferToThread XMLRPC Server - Twisted - Cherrypy?
  • Firefox stellt keine Server-gesendete Ereignisverbindung wieder her
  • Streaming POST eine große Datei zu CherryPy von Python Client
  • ImportError: Kein Modul namens http.cookies Fehler bei der Installation von cherrypy 3.2
  • Wie kann man die Anforderungsverarbeitung in Cherrypy beenden?
  • Cherry py auto herunterladen datei
  • Es gibt ein paar Beispiele für die Verwendung von BackgroundTask ( wie diese ), aber ich habe noch eine zu finden, die sich mit der Rücksendung von Daten befasst, oder eine, die mit Aufgaben arbeitet, die so schnell wie möglich laufen, im Gegensatz zu einem festen Zeitplan.

    Ich bin nicht mit der BackgroundTask Lösung verheiratet, also wenn jemand eine Alternative anbieten könnte, wäre ich mehr als glücklich. Es fühlt sich an wie es eine Lösung innerhalb des Rahmens aber gibt.

  • Ansprechzeit für Urllib in Python
  • Mit Python, um in Website zu registrieren, füllen Sie ein Formular, dann abmelden
  • Was soll ich tun, wenn socket.setdefaulttimeout () nicht funktioniert?
  • Python-Byte-Typ in String ändern
  • Drucken Sie den Quellcode in python aus
  • Python authentifizieren und starten private Seite mit webbrowser, urllib und CookieJar
  • One Solution collect form web for “Wie man Daten von einer CherryPy BackgroundTask zurückgibt, die so schnell wie möglich läuft”

    Führen Sie keine Hintergrundaufgabe mit der BackgroundTask Lösung aus, da es in einem Thread läuft und aufgrund der GIL wird cherrypy nicht in der Lage sein, neue Anfragen zu beantworten. Verwenden Sie eine Warteschlangenlösung, die Ihre Hintergrundaufgaben in einem anderen Prozess ausführt , wie Celery oder RQ .

    Ich werde im Detail ein Beispiel mit RQ entwickeln. RQ verwendet Redis als Message Broker, also müssen Sie zunächst Redis installieren und starten.

    Dann erstellen Sie ein Modul ( mytask in meinem Beispiel) mit der langen Zeit laufen Hintergrund Methoden:

     import time def long_running_task(value): time.sleep(15) return len(value) 

    Starten Sie eine (oder mehr als eine, wenn Sie Aufgaben parallel ausführen möchten) RQ Arbeiter, es ist wichtig, dass die Python, die Ihre Arbeiter läuft, Zugriff auf Ihr mytask Modul hat (Exportieren Sie den PYTHONPATH, bevor Sie den Arbeiter laufen lassen, wenn Ihr Modul nicht bereits vorhanden ist der Weg):

     # rq worker 

    Oben hast du eine sehr einfache cherrypy webapp, die zeigt, wie man die RQ-Warteschlange benutzt:

     import cherrypy from redis import Redis from rq import Queue from mytask import long_running_task class BackgroundTasksWeb(object): def __init__(self): self.queue = Queue(connection=Redis()) self.jobs = [] @cherrypy.expose def index(self): html = ['<html>', '<body>'] html += ['<form action="job">', '<input name="q" type="text" />', '<input type="submit" />', "</form>"] html += ['<iframe width="100%" src="/results" />'] html += ['</body>', '</html>'] return '\n'.join(html) @cherrypy.expose def results(self): html = ['<html>', '<head>', '<meta http-equiv="refresh" content="2" >', '</head>', '<body>'] html += ['<ul>'] html += ['<li>job:{} status:{} result:{} input:{}</li>'.format(j.get_id(), j.get_status(), j.result, j.args[0]) for j in self.jobs] html += ['</ul>'] html += ['</body>', '</html>'] return '\n'.join(html) @cherrypy.expose def job(self, q): job = self.queue.enqueue(long_running_task, q) self.jobs.append(job) raise cherrypy.HTTPRedirect("/") cherrypy.quickstart(BackgroundTasksWeb()) 

    In einer Produktion webapp würde ich jinja2 Template Engine verwenden, um die html zu generieren, und wahrscheinlich Webseiten, um den Jobstatus im Webbrowser zu aktualisieren.

    Python ist die beste Programmiersprache der Welt.