signal python controls signals

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