signal - ¿Cómo capturo SIGINT en Python?
scipy signal python (9)
Sin embargo, otro fragmento
main
referido como la función principal y exit_gracefully
como el controlador CTRL + c
if __name__ == ''__main__'':
try:
main()
except KeyboardInterrupt:
pass
finally:
exit_gracefully()
Estoy trabajando en un script de Python que inicia varios procesos y conexiones de base de datos. De vez en cuando quiero matar el script con una señal Ctrl + C , y me gustaría hacer algo de limpieza.
En Perl yo haría esto:
$SIG{''INT''} = ''exit_gracefully'';
sub exit_gracefully {
print "Caught ^C /n";
exit (0);
}
¿Cómo hago el análogo de esto en Python?
Adapté el código de @udi para admitir múltiples señales (nada especial):
class GracefulInterruptHandler(object):
def __init__(self, signals=(signal.SIGINT, signal.SIGTERM)):
self.signals = signals
self.original_handlers = {}
def __enter__(self):
self.interrupted = False
self.released = False
for sig in self.signals:
self.original_handlers[sig] = signal.getsignal(sig)
signal.signal(sig, self.handler)
return self
def handler(self, signum, frame):
self.release()
self.interrupted = True
def __exit__(self, type, value, tb):
self.release()
def release(self):
if self.released:
return False
for sig in self.signals:
signal.signal(sig, self.original_handlers[sig])
self.released = True
return True
Este código admite la llamada de interrupción del teclado ( SIGINT
) y el SIGTERM
( kill <process>
)
De la here de Python:
import signal
import time
def handler(signum, frame):
print ''Here you go''
signal.signal(signal.SIGINT, handler)
time.sleep(10) # Press Ctrl+c here
En contraste con share su respuesta, yo uso un objeto simple. Esto me da la posibilidad de analizar este controlador a todos los hilos que deben detenerse en la seguridad.
class SIGINT_handler():
def __init__(self):
self.SIGINT = False
def signal_handler(self, signal, frame):
print(''You pressed Ctrl+C!'')
self.SIGINT = True
handler = SIGINT_handler()
signal.signal(signal.SIGINT, handler.signal_handler)
En otra parte
while True:
# task
if handler.SIGINT:
break
Puede manejar CTRL + C capturando la excepción KeyboardInterrupt
. Puede implementar cualquier código de limpieza en el controlador de excepciones.
Puede tratarlo como una excepción (KeyboardInterrupt), como cualquier otra. Cree un nuevo archivo y ejecútelo desde su shell con el siguiente contenido para ver a qué me refiero:
import time, sys
x = 1
while True:
try:
print x
time.sleep(.3)
x += 1
except KeyboardInterrupt:
print "Bye"
sys.exit()
Puede usar las funciones en el here incorporado de Python para configurar los manejadores de señal en python. Específicamente, la función signal.signal(signalnum, handler)
se utiliza para registrar la función del handler
para signal signalnum
.
Registre su manejador con signal.signal
como este:
#!/usr/bin/env python
import signal
import sys
def signal_handler(sig, frame):
print(''You pressed Ctrl+C!'')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print(''Press Ctrl+C'')
signal.pause()
Código adaptado desde here .
Más documentación sobre la signal
se puede encontrar here .
Y como gestor de contexto:
import signal
class GracefulInterruptHandler(object):
def __init__(self, sig=signal.SIGINT):
self.sig = sig
def __enter__(self):
self.interrupted = False
self.released = False
self.original_handler = signal.getsignal(self.sig)
def handler(signum, frame):
self.release()
self.interrupted = True
signal.signal(self.sig, handler)
return self
def __exit__(self, type, value, tb):
self.release()
def release(self):
if self.released:
return False
signal.signal(self.sig, self.original_handler)
self.released = True
return True
Usar:
with GracefulInterruptHandler() as h:
for i in xrange(1000):
print "..."
time.sleep(1)
if h.interrupted:
print "interrupted!"
time.sleep(2)
break
Manejadores anidados:
with GracefulInterruptHandler() as h1:
while True:
print "(1)..."
time.sleep(1)
with GracefulInterruptHandler() as h2:
while True:
print "/t(2)..."
time.sleep(1)
if h2.interrupted:
print "/t(2) interrupted!"
time.sleep(2)
break
if h1.interrupted:
print "(1) interrupted!"
time.sleep(2)
break
Desde aquí: https://gist.github.com/2907502