2014-04-07 4 views
5

Version Info auf Standard:Python SIGINT zurücksetzen Signal-Handler

  • OS: Windows 7
  • Python Version 3.3.5

Unten ist kleines Stück Testcode ich um spielte. Das Ziel war, zu ignorieren, dass CTRL-C gedrückt wurde, während bestimmter Code ausgeführt wurde, nach dem das CTRL-C Verhalten wiederhergestellt wurde.

import signal 
import time 

try: 
    # marker 1 
    print('No signal handler modifications yet') 
    print('Sleeping...') 
    time.sleep(10) 

    # marker 2 
    signal.signal(signal.SIGINT, signal.SIG_IGN) 
    print('Now ignoring CTRL-C') 
    print('Sleeping...') 
    time.sleep(10) 

    # marker 3 
    print('Returning control to default signal handler') 
    signal.signal(signal.SIGINT, signal.SIG_DFL) 
    print('Sleeping...') 
    time.sleep(10) 

except KeyboardInterrupt: 
    print('Ha, you pressed CTRL-C!') 

Was ich beobachtet habe, während sie mit diesen Herumspielen:

  • CTRL-C geschickt zwischen Marker 1 und Marker 2 wird von den Exception-Handler verarbeitet werden (wie erwartet).
  • CTRL-C zwischen Marker 2 und Markierung 3 wird ignoriert (noch, wie erwartet) gesendet
  • CTRL-C nach Marker gesendet 3 verarbeitet ist, aber nicht Sprung zu der Ausnahmebehandlungsroutine. Stattdessen beendet Python nur sofort.

Auch bedenken Sie:

>>>import signal 

>>>signal.getsignal(signal.SIGINT) 
<built-in function default_int_handler> 

>>> signal.getsignal(signal.SIGINT) is signal.SIG_DFL 
False 

>>> signal.signal(signal.SIGINT, signal.SIG_DFL) 
<built-in function default_int_handler> 

>>> signal.getsignal(signal.SIGINT) is signal.SIG_DFL 
True 

So zunächst, während der Signal-Handler die Standardsignalbehandlungsroutine angesehen wird, scheint es eine andere Handler als die von SIG_DFL definiert zu sein.

Wenn jemand etwas Licht darauf werfen könnte, insbesondere während der Ausnahmebehandler ignoriert wird, nachdem der Signalhandler auf SIG_DFL wiederhergestellt wurde.

+0

Es gibt Probleme mit SIGINT unter Windows, siehe http: // stack overflow.com/questions/16686510/how-doi-i-capture-sigint-in-python-on-windows und http://bugs.python.org/issue18040 – cdarke

Antwort

7

Python installiert seinen eigenen SIGINT Handler, um KeyboardInterrupt Ausnahmen zu erhöhen. Das Setzen des Signals auf SIG_DFL wird diesen Handler nicht wiederherstellen, sondern den "Standard" -Handler des Systems selbst (der den Interpreter beendet).

Sie haben die Original-Handler zu speichern und diese Handler wiederherstellen, wenn Sie fertig sind:

from contextlib import contextmanager 

@contextmanager 
def sigint_ignored(): 
    original_sigint_handler = signal.getsignal(signal.SIGINT) 
    signal.signal(signal.SIGINT, signal.SIG_IGN) 
    try: 
     print('Now ignoring CTRL-C') 
     yield 
    except: 
     raise # Exception is dropped if we don't reraise it. 
    finally: 
     print('Returning control to default signal handler') 
     signal.signal(signal.SIGINT, original_sigint_handler) 

:

original_sigint_handler = signal.getsignal(signal.SIGINT) 

# Then, later... 
signal.signal(signal.SIGINT, original_sigint_handler) 

Wie Kindall zu Recht in den Kommentaren sagt, Sie dies als ein context manager ausdrücken Sie können es wie folgt verwenden:

# marker 1 
print('No signal handler modifications yet') 
print('Sleeping...') 
time.sleep(10) 

# marker 2 
with sigint_ignored(): 
    print('Sleeping...') 
    time.sleep(10) 

# marker 3 
print('Sleeping...') 
time.sleep(10) 
+3

Klingt wie ein Job für einen Kontextmanager! – kindall

+2

Beachten Sie, dass der Standard-Handler immer als 'signal.default_int_handler' verfügbar ist. – eryksun

Verwandte Themen