2014-04-07 13 views
5
informazioni

versione di default:Ripristina Python SIGINT gestore di segnale

  • OS: Windows 7 versione
  • Python 3.3.5

seguito è piccolo pezzo di codice di prova stavo giocando intorno. L'obiettivo era ignorare CTRL-C mentre veniva eseguito un determinato codice, dopo il quale il comportamento CTRL-C veniva ripristinato.

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!') 

quello che ho osservato durante il gioco in giro con questo:

  • CTRL-C inviato tra marker 1 e marcatore 2 saranno trattati dal gestore di eccezioni (come previsto).
  • CTRL-C inviati tra marcatore 2 e marcatore 3 viene ignorato (ancora, come previsto)
  • CTRL-C inviato dopo marcatore 3 viene preparata, ma sarà non salto per il gestore di eccezioni. Invece, Python solo termina immediatamente.

Inoltre, considerare questo:

>>>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 

Quindi inizialmente, mentre il gestore di segnale è considerato il gestore di segnale di default, sembra essere un gestore diverso da quello definito da SIG_DFL.

Se qualcuno può far luce su questo, specialmente mentre il gestore di eccezioni viene ignorato dopo aver ripristinato il gestore di segnale su SIG_DFL.

+0

Ci sono problemi con SIGINT su Windows, vedere http: // stack overflow.com/questions/16686510/how-do-i-capture-sigint-in-python-on-windows e http://bugs.python.org/issue18040 – cdarke

risposta

7

Python installa il proprio gestore SIGINT per aumentare le eccezioni KeyboardInterrupt. L'impostazione del segnale su SIG_DFL non ripristinerà quel gestore, ma il gestore "standard" del sistema stesso (che termina l'interprete).

è necessario memorizzare il gestore originale e ripristinare tale gestore quando hai finito:

original_sigint_handler = signal.getsignal(signal.SIGINT) 

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

Come Kindall dice giustamente nei commenti, è possibile esprimere questa come una context manager:

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) 

È possibile utilizzarlo in questo modo:

# 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

Sembra un lavoro per un gestore di contesto! – kindall

+2

Si noti che il gestore predefinito è sempre disponibile come "signal.default_int_handler". – eryksun

Problemi correlati