Flask mit multiprocessing.Queue()

Django, Flask, Bottle, WSGI, CGI…
Antworten
McChaos
User
Beiträge: 7
Registriert: Freitag 8. März 2019, 17:42

Hallo,

ich bin noch recht unerfahren mit Flask (arbeite gerade am ersten Projekt damit) und überlege nun, wie ich Daten von einem separaten Prozess über multiprocessing.Queue() empfangen und verarbeiten kann. Der Prozess läuft ständig im Hintergrund unabhängig von dieser Applikation.
Die Daten kommen asynchron über die Queue (also ohne vorherige Anforderung) und ich finde keinen Ansatzpunkt im Flask, wie ich auf die Queue warten kann oder (alternativ) wie ich zuverlässig die Queue alle paar 100ms abfragen kann. Alle anderen Aktivitäten in der GUI sollen natürlich nicht blockiert werden....

Der Hintergrundprozess stammt auch von mir, insofern kann ich die Schnittstelle anpassen (muss also nicht zwingend multiprocessing.Queue() sein). Allerdings will ich diesen als unabhängiges Projekt erhalten und die Schnittstelle muss bidirektional funktionieren.

Hat jemand einen Ansatz, wie das zu lösen wäre? Ein Link zu Quelltextbeispielen wäre auch super...

Vielen Dank!
Thomas
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Was hat denn Multiprocessing damit zu tun, wenn es sich - und so verstehe ich dich - um ein separates Programm handelt?
Flask ist ein Webframework. Wie soll da eine GUI blockieren?

Eine Möglichkeit:
Schreib das Ergebis in eine Datenbank. Der Server requestet per JavaScript eine URL und die sagt ihm, dass er es noch einmal versuchen muss oder liefert die entsprechenden Daten.
McChaos
User
Beiträge: 7
Registriert: Freitag 8. März 2019, 17:42

Mit Multiprocessing hat das nicht viel zu tun, aber mit multiprocessing.Queue(), diese würde ich gern als Bindeglied zwischen den beiden Prozessen verwenden. Das der Hintergrundprozess extern gestartet wird und dauernd läuft, sollte ja kein Problem sein....

Wenn ich Dich richtig verstehe, schickt der verbundene Client dann ständig Anfragen ob was da ist? Damit könnte der Flask Server dann auch regelmäßig die Queue abfragen.
Allerdings hätte ich das schon gern eventbasiert gelöst - sobald neue Daten vom Hintergrundprozess da sind, wird erst eine Aktion im Flaskserver ausgelöst und wenn kein Client verbunden ist, werden die Daten ignoriert. Polling wäre nur die Notlösung, wenn es gar nicht anders geht (Ich finds persönlich halt nicht schön)
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

multiprocessing.Queue tuts nicht. Das ist pipe-basiert und hart mit der Idee von multiprocessing verheiratet, ein drop-in für threads zu sein.

Stattdessen kannst du wahlweise beliebige andere IPC Mechanismen nutzen. Meine Präferenz ist nanomsg. Falls du sicherstellen willst, dass keine Nachrichten verloren gehen, zb weil der Flask service neu gestartet wird, nimm eine persistente Queue, wie zb RabbitMQ.

Siehe zb hier: https://flask-socketio.readthedocs.io/e ... index.html
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

Auf die Nutzung einer externen Message Queue-Middleware hat __deets__ ja bereits hingewiesen. Da gibt es ja eine ganze Menge, der Platzhirsch dürfte vermutlich Apache Kafka sein, aber auch das bereits von __deets__ genannte RabbitMQ erfreut sich großer Beliebtheit.

Ich ganz persönlich bevorzuge in solchen Fällen eine sehr kleine, jedoch besonders performante Software mit den Namen "Redis", zu finden unter [1]. Neuere Versionen von Redis enthalten für Message Queues ein neues Feature namens Streams, allerdings ist die akutelle Version von Redis noch nicht in den verbreiteten Linux-Distributionen enthalten, so daß wahlweise eine aktuelle Version selbst übersetzt und installiert werden müßte. In diesem Anwendungsfall kann für ältere Versionen mit einer Liste gearbeitet werden. Übrigens: wenn das alles ohnehin lokal auf derselben Maschine läuft, kann Redis auch über einen lokalen UNIX-Socket angesprochen werden, was diese ohnehin schon extrem performante Software noch ein bisschen schneller macht. Wer dabei das TCP-Interface abschaltet, sorgt gleichzeitig dafür, daß nur lokale Prozesse auf Redis zugreifen können.

Was mir allerdings noch nicht ganz klar ist: wenn Du ohnehin an eine Flask-Applikation liefern willst -- die ja einen Netzwerk-Endpunkt hat, der HTTP versteht -- warum liefert Dein Hintergrundprozeß die Daten nicht einfach über HTTPS? und (zum Beispiel) JSON ein? Mit dem Python-Modul "requests" ist das ein Kinderspiel, und danach mußt Du Dir (eventuell) nurmehr Gedanken über eine Persistierung machen.


[1] https://redis.io/
McChaos
User
Beiträge: 7
Registriert: Freitag 8. März 2019, 17:42

Vielen Dank für Eure Hinweise! Ich schau mir die ganzen Varianten erst mal an.
Antworten