How to prevent a block of code from being interrupted by KeyboardInterrupt in Python?
我正在编写一个程序,通过pickle模块缓存一些结果。此时发生的情况是,如果我在执行
有没有办法使
1 2 3 4 5 6 7 8 9 10 | try: file = open(path, 'w') dump(obj, file) file.close() except KeyboardInterrupt: file.close() file.open(path,'w') dump(obj, file) file.close() raise |
如果操作被中断,重新启动它似乎很愚蠢,所以我正在寻找一种延迟中断的方法。我该怎么做?
下面是一个上下文管理器,它为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import signal import logging class DelayedKeyboardInterrupt(object): 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() |
将函数放入线程中,等待线程完成。
不能中断Python线程,除非使用特殊的C API。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 |
看看中断是如何延迟到线程结束的?
在这里,它适合您的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() |
使用信号模块在处理期间禁用SIGINT:
1 2 3 | s = signal.signal(signal.SIGINT, signal.SIG_IGN) do_important_stuff() signal.signal(signal.SIGINT, s) |
在我看来,用线程来解决这个问题是一种过分的杀伤力。在成功写入之前,只需在循环中执行以下操作,即可确保正确保存文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def saveToFile(obj, filename): file = open(filename, 'w') cPickle.dump(obj, file) file.close() return True done = False while not done: try: done = saveToFile(obj, 'file') except KeyboardInterrupt: print 'retry' continue |
这个问题是关于阻止
使用原子写入,要么整个文件被正确写入,要么什么也不做。StackOverflow有多种解决方案,但就我个人而言,我喜欢使用AtomicWrites库。
运行
1 2 3 4 | from atomicwrites import atomic_write with atomic_write(path, overwrite=True) as file: dump(obj, file) |