2017-06-16 2 views
0

Ich habe ein Python-Skript, das einen grundlegenden Webserver startet und auf bestimmte Eingaben reagiert, das funktioniert gut. Ich habe auch das Windows-Taskleistensymbol funktioniert (zeigt eine Ico-Datei) - aber im Moment scheint das Skript an der Stelle des Systemsymbols zu blockieren.Python - HTTP-Server starten und Windows-System-Tray setzen

Ich möchte nur einen Python-HTTP-Server hören und ein Taskleistensymbol anzeigen, während das Skript ausgeführt wird - dies ist bereits ein verstecktes Python-Fenster und ich würde gerne wissen, ob es aus irgendeinem Grund fehlschlägt.

Muss ich zwei separate Threads starten? oder gibt es einen besseren Weg, dies zu tun? hier war mein Original-Code (Auszug only):

hover_text = "My Tray Icon Text" 
def hello(sysTrayIcon): print "Hello World." 
def simon(sysTrayIcon): print "Hello Simon." 
def switch_icon(sysTrayIcon): 
    pass 
menu_options = (('Say Hello', None, hello), 
       ('Switch Icon', None, switch_icon), 
       ('A sub-menu', None, (('Say Hello to Simon', None, simon), 
               ('Switch Icon', None, switch_icon), 
              )) 
       ) 
def bye(sysTrayIcon): 
    print ("Server stopped by user") 
    sys.exit() 
    # server.shutdown() 

print("setting system tray icon") 
SysTrayIcon("hazard.ico", hover_text, menu_options, on_quit=bye, default_menu_index=1) 

print("starting server") 


#local only 
#server = HTTPServer(('localhost', 9006), GetHandler) 

#listen on all interfaces 
server = HTTPServer(('0.0.0.0', 9006), GetHandler) 

#print 'Starting server, use to stop' 
server.serve_forever() 

Ich habe versucht, den Server zu starten, bevor das System Tray-Icon bewegt wie diese Einstellung:

thread = threading.Thread(target = server.serve_forever()) 

aber es blockiert dann auf Serverstartstück, kein Das Symbol ist gesetzt.

Ich habe auch versucht, diese

from SocketServer import ThreadingMixIn 

class ThreadingServer(ThreadingMixIn, HTTPServer): 
    pass 

srvr = ThreadingServer(('0.0.0.0', 9006), GetHandler) 
srvr.serve_forever() 

reference aber es blockiert noch am Server Stück.

Soll ich vielleicht Multiprocessing anstelle von Multi-Threading verwenden? das Skript ist ziemlich klein & trivial.

Antwort

0

Ich nehme an, der Anruf SysTrayIcon() blockiert (nicht vertraut mit dieser Funktion und das Bereitstellungsmodul fehlt aus dem Codebeispiel).

Wenn ja, dann ist eine Lösung, den Server in einem separaten Thread zu starten, wie Sie es versucht haben. Eine Sache zu beachten ist, dass, wenn ein Thread gestartet wird, eine Referenz an die Funktion für die target der Thread() übergeben werden sollte.

So ist der Code, den Sie brauchen, ist wie:

server_thread = threading.Thread(target=server.serve_forever) 
server_thread.start() 

Statt die Methode aufrufen. Im Codebeispiel wird server.serve_forever aufgerufen, daher der Block (diese Methode blockiert die Annahme und Verarbeitung von HTTP-Anfragen für immer).

Auch wenn Sie die ThreadingMixIn aus der SocketServer wählen, sollte der Aufruf an serve_forever in einem separaten Thread erfolgen. Die ThreadingMixIn ermöglicht es dem Server, jede HTTP-Anforderung in einem anderen Thread zu bedienen, aber der Aufruf an serve_forever blockiert weiterhin den aktuellen Thread.

Ich würde auch vorschlagen, über eine ordnungsgemäße Möglichkeit nachzudenken, den Server-Thread zu stoppen (mit threading.Event zum Beispiel), wenn Ihre App aufhören wird. Oder vielleicht ist es einfach, die SysTrayIcon() in einem anderen Thread anzurufen:

threading.Thread(target=SysTrayIcon, args=("hazard.ico", hover_text, menu_options), kwargs=dict(on_quit=bye, default_menu_index=1)) 
+0

Vielen Dank für Ihre Antwort. Entschuldigung, hier ist ein Verweis für den Tray Icon Code: http://www.brunningonline.net/simon/blog/archives/SysTrayIcon.py.html Ich verwende bereits einen Verweis auf die Funktion, aber es blockiert immer noch auf myThread1.start() Ich werde weiter damit spielen und sehen, was ich tun kann. und ja, mach dir keine Sorgen die sys, exit war nur ein Platzhalter. ;-) – TheDavil

+0

Ich habe deine zweite Bearbeitung auch versucht, das rufende Systray-Icon in einem anderen Thread. Sie blockieren beide aus irgendeinem Grund. Ich habe das Gefühl, ich mache das alles falsch, aber werde es bald herausfinden – TheDavil

+0

Ich habe keine Erfahrung mit Python Win32 API, einige GUI-Frameworks erfordern die Verwendung des Hauptthreads für einige Operationen. Sie können solche Tricks finden. Wenn Sie blockierende Aufrufe erkennen und sie in Threads starten, blockiert der Haupt-Thread im Allgemeinen nicht (es sei denn, ein Thread ist eine "busy loop", bei der andere Threads nicht ordnungsgemäß verarbeitet werden). – farzad