如何在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
您可以通过捕获KeyboardInterrupt
exception来处理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
)和SIGTERM
( kill <process>
)
您可以使用Python内置信号模块中的函数来设置python中的信号处理程序。 具体来说, signal.signal(signalnum, handler)
函数用于注册信号signalnum
的handler
函数。
另一个片段
将main exit_gracefully
为主函数, exit_gracefully
以CTRL + 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