如何在Python中捕获SIGINT?

我正在研究一个启动多个进程和数据库连接的python脚本。 我不时地想用Ctrl + C信号杀死脚本,我想做一些清理工作。

在Perl中,我会这样做:

$SIG{'INT'} = 'exit_gracefully'; sub exit_gracefully { print "Caught ^C \n"; exit (0); } 

我如何在Python中做类似的事情?

signal.signal注册你的处理程序,像这样:

 #!/usr/bin/env python import signal import sys def signal_handler(signal, frame): print('You pressed Ctrl+C!') sys.exit(0) signal.signal(signal.SIGINT, signal_handler) print('Press Ctrl+C') signal.pause() 

代码从这里改编而来。

有关signal更多文档可以在这里find。

你可以把它像一个exception(KeyboardInterrupt),像任何其他。 创build一个新的文件,并从你的shell中运行下面的内容来看看我的意思:

 import time, sys x = 1 while True: try: print x time.sleep(.3) x += 1 except KeyboardInterrupt: print "Bye" sys.exit() 

作为上下文pipe理者:

 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 

使用:

 with GracefulInterruptHandler() as h: for i in xrange(1000): print "..." time.sleep(1) if h.interrupted: print "interrupted!" time.sleep(2) break 

嵌套处理程序:

 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 

从这里: https : //gist.github.com/2907502

您可以通过捕获KeyboardInterruptexception来处理CTRL + C。 您可以在exception处理程序中实现任何清理代码。

从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 

我修改了@udi的代码来支持多个信号(没什么奇怪的):

 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 

这段代码支持键盘中断调用( SIGINT )和SIGTERMkill <process>

您可以使用Python内置信号模块中的函数来设置python中的信号处理程序。 具体来说, signal.signal(signalnum, handler)函数用于注册信号signalnumhandler函数。

另一个片段

将main exit_gracefully为主函数, exit_gracefullyCTRL + c处理函数的formsexit_gracefully

 if __name__ == '__main__': try: main() except KeyboardInterrupt: pass finally: exit_gracefully() 

与Matt J的回答相反,我使用了一个简单的对象。 这给了我可能parsing这个处理程序到所有需要被停止securlery的线程。

 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) 

别处

 while True: # task if handler.SIGINT: break