2010-09-24 6 views
40

ich diese meine einfachen Code renne:Threading ignoriert KeyboardInterrupt Ausnahme

import threading, time 

class reqthread (threading.Thread): 
    def __init__ (self): 
    threading.Thread.__init__(self) 

    def run (self): 
    for i in range(0,10): 
     time.sleep(1) 
     print '.' 

try: 
    thread=reqthread() 
    thread.start() 
except (KeyboardInterrupt, SystemExit): 
    print '\n! Received keyboard interrupt, quitting threads.\n' 

Aber wenn ich es laufen, gibt es

$ python prova.py 
` 
. 
. 
^C. 
. 
. 
. 
. 
. 
. 
. 
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored 
` 

In der Tat Python Thread ignorieren meine Ctrl +C Tastatur Interrupt und druckt nicht Received Keyboard Interrupt. Warum? Was ist falsch an diesem Code?

Antwort

50

Versuchen

try: 
    thread=reqthread() 
    thread.daemon=True 
    thread.start() 
    while True: time.sleep(100) 
except (KeyboardInterrupt, SystemExit): 
    print '\n! Received keyboard interrupt, quitting threads.\n' 

Ohne den Aufruf von time.sleep, der Hauptprozess zu früh aus dem try...except Block springt, so wird die KeyboardInterrupt nicht gefangen. Mein erster Gedanke war thread.join zu verwenden, aber das scheint den Hauptprozess (ohne Berücksichtigung KeyboardInterrupt) zu blockieren, bis die thread beendet ist.

thread.daemon=True bewirkt, dass der Thread, wenn endet der Hauptprozess zu beenden.

+4

Ich glaube, ein Timeout auf 'join', das heißt' während thread.isAlive: Thread.Join (5) 'wird auch die Haupt-Thread, die auf Ausnahmen halten arbeiten. –

+11

'thread.daemon = true' tatsächlich wird nicht empfohlen, da es nicht der Thread keine Ressourcen hinter sich gelassen, um aufzuräumen erlaubt ... –

7

Um die Änderungen empfohlen zusammenfassen für mich in thecomments, die folgenden Werke gut:

try: 
    thread = reqthread() 
    thread.start() 
    while thread.isAlive(): 
    thread.join(1) # not sure if there is an appreciable cost to this. 
except (KeyboardInterrupt, SystemExit): 
    print '\n! Received keyboard interrupt, quitting threads.\n' 
    sys.exit() 
+0

Ist„Thread.Join()“immer und immer wieder in den„während thread.isAlive Aufruf(): "Eine gute Sache/ist das wichtig? – DevPlayer

+0

Ich persönlich weiß es nicht; Kann es einen Versuch wert sein, einen Benchmark zu erstellen, wenn dir das etwas bedeutet? – rattray

+1

Beachten Sie, dass exit() und sys.exit() nicht identisch sind. Es wird empfohlen, sys.exit() zu verwenden. – DevPlayer

0

My (hacky) Lösung ist, Affe-Patch Thread.join() wie folgt aus:

def initThreadJoinHack(): 
    import threading, thread 
    mainThread = threading.currentThread() 
    assert isinstance(mainThread, threading._MainThread) 
    mainThreadId = thread.get_ident() 
    join_orig = threading.Thread.join 
    def join_hacked(threadObj, timeout=None): 
    """ 
    :type threadObj: threading.Thread 
    :type timeout: float|None 
    """ 
    if timeout is None and thread.get_ident() == mainThreadId: 
     # This is a HACK for Thread.join() if we are in the main thread. 
     # In that case, a Thread.join(timeout=None) would hang and even not respond to signals 
     # because signals will get delivered to other threads and Python would forward 
     # them for delayed handling to the main thread which hangs. 
     # See CPython signalmodule.c. 
     # Currently the best solution I can think of: 
     while threadObj.isAlive(): 
     join_orig(threadObj, timeout=0.1) 
    else: 
     # In all other cases, we can use the original. 
     join_orig(threadObj, timeout=timeout) 
    threading.Thread.join = join_hacked 
2

leichte Modifikation von Ubuntus Lösung.

tread.daemon Entfernen = True wie Eric vorgeschlagen und den Schlaf Schleife durch signal.pause ersetzt():

import signal 
try: 
    thread=reqthread() 
    thread.start() 
    signal.pause() # instead of: while True: time.sleep(100) 
except (KeyboardInterrupt, SystemExit): 
    print '\n! Received keyboard interrupt, quitting threads.\n' 
+1

Schön - aber leider nicht unter Windows unterstützt –

0

die try ... except in jedem Thread Putting und auch ein signal.pause() in wahrmain() Werke für mich.

beobachten obwohl für import lock aus. Ich vermute, das ist der Grund, warum Python ctrl-C standardmäßig nicht löst.

Verwandte Themen