2013-10-29 6 views
7

Ich schreibe ein Python-Skript, das einen Thread ausführen muss, der auf einen Netzwerk-Socket hört.Python-Programm mit Thread kann nicht fangen STRG + C

Ich habe Probleme mit ihm zu töten Ctrl +c mit dem Code unten:

#!/usr/bin/python 

import signal, sys, threading 

THREADS = [] 

def handler(signal, frame): 
    global THREADS 
    print "Ctrl-C.... Exiting" 
    for t in THREADS: 
     t.alive = False 
    sys.exit(0) 

class thread(threading.Thread): 
    def __init__(self): 
     self.alive = True 
     threading.Thread.__init__(self) 


    def run(self): 
     while self.alive: 
      # do something 
      pass 

def main(): 
    global THREADS 
    t = thread() 
    t.start() 
    THREADS.append(t) 

if __name__ == '__main__': 
    signal.signal(signal.SIGINT, handler) 
    main() 

Freuen uns über jede Beratung, wie Ctrl fangen + c und beenden Sie das Skript .

Antwort

3

Das liegt daran, dass Signale nur vom Hauptthread abgefangen werden können. Und hier endete der Hauptteil seines Lebens vor langer Zeit (die Anwendung wartet darauf, dass dein Thread beendet wird). Versuchen Sie,

while True: 
    sleep(1) 

bis zum Ende Ihrer main() (und natürlich from time import sleep an der Spitze).

oder als Kevin gesagt:

for t in THREADS: 
    t.join(1) # join with timeout. Without timeout signal cannot be caught. 
+0

Die Verwendung von 'Thread.join()' ist vorzuziehen gegenüber Spin-Looping mit Timeouts. –

+0

Warum können Signale nur vom Hauptkabel abgefangen werden? – tristan

+1

http://docs.python.org/2/library/signal.html 7. Punkt. Nimm es als Gesetz :) – jaor

8

Das Problem ist, dass, nachdem die Ausführung des Hauptthreads abfällt (nach main() zurückgegeben), das threading Modul pausiert, für die anderen Threads warten zu beenden, Schlösser verwenden ; und Sperren können nicht mit Signalen unterbrochen werden. Dies ist zumindest in Python 2.x der Fall.

Eine einfache Lösung besteht darin, das Abfallen des Hauptthreads zu vermeiden, indem eine Endlosschleife hinzugefügt wird, die eine Funktion aufruft, die ruht, bis eine Aktion verfügbar ist, wie select.select(). Wenn Sie den Hauptthread überhaupt nicht benötigen, verwenden Sie signal.pause(). Beispiel:

if __name__ == '__main__': 
    signal.signal(signal.SIGINT, handler) 
    main() 
    while True:   # added 
     signal.pause() # added 
Verwandte Themen