如何防止Python中代码块被KeyboardInterrupt中断?
在进行dump
操作保存数据的时候,如果你按下了ctrl+c,这个中断会导致文件损坏(也就是说,文件只写了一部分,无法再被load
加载)。
有没有办法让dump
,或者说任何一段代码,不被中断呢?
我现在的解决办法是这样的:
try:
file = open(path, 'w')
dump(obj, file)
file.close()
except KeyboardInterrupt:
file.close()
file.open(path,'w')
dump(obj, file)
file.close()
raise
如果操作被中断了,重新开始这个操作似乎有点傻,那有没有办法让中断延后呢?
9 个回答
38
可以使用 signal 模块来在整个程序运行期间禁用 SIGINT 信号:
s = signal.signal(signal.SIGINT, signal.SIG_IGN)
do_important_stuff()
signal.signal(signal.SIGINT, s)
91
下面是一个上下文管理器,它会为 SIGINT
信号设置一个处理程序。也就是说,当这个上下文管理器的信号处理程序被调用时,它会延迟处理这个信号,只有在上下文管理器退出的时候,才会把信号传递给原来的处理程序。
import signal
import logging
class DelayedKeyboardInterrupt:
def __enter__(self):
self.signal_received = False
self.old_handler = signal.signal(signal.SIGINT, self.handler)
def handler(self, sig, frame):
self.signal_received = (sig, frame)
logging.debug('SIGINT received. Delaying KeyboardInterrupt.')
def __exit__(self, type, value, traceback):
signal.signal(signal.SIGINT, self.old_handler)
if self.signal_received:
self.old_handler(*self.signal_received)
with DelayedKeyboardInterrupt():
# stuff here will not be interrupted by SIGINT
critical_code()
54
把这个功能放到一个线程里,然后等这个线程完成。
在Python中,线程是不能被随便打断的,除非使用一种特殊的C语言接口。
import time
from threading import Thread
def noInterrupt():
for i in xrange(4):
print i
time.sleep(1)
a = Thread(target=noInterrupt)
a.start()
a.join()
print "done"
0
1
2
3
Traceback (most recent call last):
File "C:\Users\Admin\Desktop\test.py", line 11, in <module>
a.join()
File "C:\Python26\lib\threading.py", line 634, in join
self.__block.wait()
File "C:\Python26\lib\threading.py", line 237, in wait
waiter.acquire()
KeyboardInterrupt
你看,打断的操作是等到线程完成后才进行的,对吧?
这里是根据你的需求做的调整:
import time
from threading import Thread
def noInterrupt(path, obj):
try:
file = open(path, 'w')
dump(obj, file)
finally:
file.close()
a = Thread(target=noInterrupt, args=(path,obj))
a.start()
a.join()