eventhandler für sockets?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Guten Morgen. Erst mal kurz vorweg - ich bin ein absoluter Python Anfänger, ich übe mich erst seit einer Woche darin. Ich habe im Studium diverse Programmiersprachen behandelt(c, c++, SQL, JavaScript, VB....). Da mir von ehemaligen Kommilitonen nahegelegt wurde das Python ganz gut und relativ einfach zu erlernen sein soll hab ich gedacht ich versuche mein nächstes kleines Privates Projekt mal hiermit.
Nachdem ich einige Beispielprogramme ausprobiert habe sollte es bei mir auch gleich losgehen. Ich möchte einen kleinen Tcp- Server haben der auf eingehende Strings reagiert und bei verschiedenen Strings verschiedene Aktionen ausführt. Für dieses Problem gibt es auch reichlich Anleitungen und kurze Beispiele im Netz. Zuletzt habe ich dieses deutsche Turorial durchgearbeitet. Die Beispiele laufen auch alle herforagend (bis auf die sache mit dem ForkingTCPServer, aber das liegt dann wohl an meinem WinXP).

Die wirklichen Probleme bekomme ich erst seit ich mir vorgenommen habe das mein Server auch eine GUI bekommen soll. Dazu muss ich sagen das meine letzten erfahrungen mit einer GUI Programmierung Jahre zurückliegen (damas QT unter c++). Ich habe also ein einfaches Beispiel für ein 'hello world' Programm mit wsPython genommen und versucht damit meinen TCP- Server zu starten.
Wenn nich nun aus dem Tutorial beispielsweise den Minimalen Server erstelle Staret mein Server zwar und läuft auch, aber durch den Aufruf von serve_forever() hängt meine gesamte GUI fest - der Server hingegen arbeitet schön weiter und beantwortet auch anfragen.
Das ganze hab ich nun schon in verschiedenen Varianten ausprobiert und immer hängt die GUI sobald ich versuche einen Server in einer Schleife laufen zu lassen.

Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht, aber gibt es eine Möglichkeit das die GUI nicht hängt, und ich einen Eventhander oder ähnliches für den Netzwerkverkehr bekomme?

Gruss Sebastian
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Lonestar hat geschrieben: Die wirklichen Probleme bekomme ich erst seit ich mir vorgenommen habe das mein Server auch eine GUI bekommen soll.
Was imho eine Unart ist ;-)
Wie wärs, die GUI als reines Frontend zum Starten / Stoppen des Servers anzusehen? Dann kannst Du per Subprocess einfach Dein Server-Script starten.
Das ganze hab ich nun schon in verschiedenen Varianten ausprobiert und immer hängt die GUI sobald ich versuche einen Server in einer Schleife laufen zu lassen.
Ist ja auch logisch, wenn das im selben Thread passiert. Eine Endlosschleife innerhalb einer GUI-Funktion / Methode führt ja dazu, dass die Hauptschleife der GUI nicht mehr durchlaufen wird! Bei Qt gibts iirc eigene Threads, bei wx müßtest Du mal gucken. Native Python Threads machen bei GUIs ja häufig Ärger - k.A. wie das bei wx ist. Also wenn Dein Server nicht als eigener Prozess laufen soll, musst Du ihn irgend wie in einem Thread starten. Mehr kann ich Dir als Lösung leider nicht anbeiten :-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Die Lösung sind Threads.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

http://wiki.wxpython.org/WorkingWithThreads
Nach 2 Minuten Suche ;-)

Sieht zwar häßlich aus - aber das kann ja auch am Browser liegen. Da es aus dem offiziellen wx-Wiki stammt, sollte das Vorgehen aber wohl i.o. sein.

(@all: Ich dachte immer GUIs und native Python Threads würden Ärger machen? Irre ich da oder hängt das vom Toolkit bzw. dem Binding ab?)
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Hyperion hat geschrieben:(@all: Ich dachte immer GUIs und native Python Threads würden Ärger machen? Irre ich da oder hängt das vom Toolkit bzw. dem Binding ab?)
Man darf, zumindest bei den mir bekannten Toolkits, nur nicht mit mehreren Threads (gleichzeitig) auf die GUI zugreifen, da das sonst zu allem Möglichen führen kann. Üblicherweise wird dazu eine Funktion aufgerufen(``wx.CallAfter`` bei wxPython, ``gobject.idle_add`` bei PyGtk), der eine Callback-Funktion übergeben wird und das Toolkit ruft dann diese Callback-Funktion in der Haupt-Event-Schleife auf, wodurch die Callback-Funktion dann im Kontext des Threads läuft, in dem auch die Haupt-Event-Schleife des Toolkits läuft. Zusätzlich gibt es bei Gtk noch die Möglichkeit von Locks, die ein Thread anfordern muss, bevor er auf Funktionen des Toolkits zugreifen kann (das kann dann nur ein Thread gleichzeitig). Wie das bei anderen Toolkits ist, weiß ich nicht.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Hyperion hat geschrieben: Was imho eine Unart ist ;-)
Wie wärs, die GUI als reines Frontend zum Starten / Stoppen des Servers anzusehen? Dann kannst Du per Subprocess einfach Dein Server-Script starten.
[...]
Also wenn Dein Server nicht als eigener Prozess laufen soll, musst Du ihn irgend wie in einem Thread starten. Mehr kann ich Dir als Lösung leider nicht anbeiten :-)
Hey, danke Hyperion und EyDu für euren Schubser in die richtige Richtung. Das mit den Threads muss ich letzte Nacht irgendwann immer überlesen haben als ich gelesen hatte das unter Win beim SocketServer der ForkingTCPServer mit mehreren Prozessen nicht unterstütz wird. Ich bin daher davon ausgegangen das mehrere Threads nicht in Frage kämen...

Ich hab mir vorhin mal aus 2 Beispielen BSP1 BSP2 aus dem Netz das Grundgerüst das ich gebrauchen könnte zusammengewürfelt. Ich befürchte der Code für euch nicht besonders übersichtlich - auch da muss ich erst wieder ein wenig fitter werden. Ich bin erst mal nur auf ein funktionierendes Gerüst aus - danach wollte ich das Ganze aufräumen. Ich poste mal der Übersichtlichkeit halber nicht hier in die Seite, da ich das zu unübersichtlich finde (wenn das bei euch doch so üblich ist kann ich das trotzdem gerne nachholen).
Also der Code zum Ganzen ist HIERzu finden.
Die gute Nachricht zuerst: Das Script läuft. Der Server wird nach einem klick auf den Button Start gestartet. Der Server beantwortet TCP- Nachrichten so wie ich es wollte.
Die schlechte Nachricht: der Server wird wohl anscheinend nicht ordnungsgemäße geschlossen. Aber das werde ich mit ein wenig Lektüre hoffentlich selber lösen.

Und nun zu meinen Fragen
1. ich hab nun schon fast 1 Stunde versucht herauszufinden was in der folgenden Funktion das win.Connect überhaupt macht (ok... mit ner Kaffepause :oops: ). Ich hab auch noch nich so wirklich rausgefunden wozu das Objekt win gehört oder wo es überhaupt herkommt... da würde mir ein Link zu ner Doku völlig genügen

Code: Alles auswählen

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

2. Ich kann von dem Objekt Server wunderbar Nachrichten mittels wx.PostEvent() an die GUI schicken. Da ich aber schon bei der Funktion der Events (Punkt 1) Probleme hatte frage ich gleich mal weiter:
Ein Serverobjekt instaziiert ja noch ein Objekt Service das die TCP- Abfragen behandelt. Ich hoffe mal das ich das einigermaßen richtig wiedergegeben habe. Mit OOP habe ich längere Zeit nicht mehr besonders intensiv zu tun gehabt. Wie sorge ich denn nun dafür das ich vom handler in der Serviceklasse auch Nachrichten an die GUI schicken kann? Muss ich mir einen Handler bauen der von der Klasse Service an die Klasse Server vermittelt so dass ich auf diesem Weg alle Nachrichten weiterreiche?
Oder gibt es andere/bessere/schönere/elegantere Möglichkeiten?

Ich bin für alle Anregungen, Ideen oder Hilfen dankbar.
Sebastian
Antworten