如何防止代码块被 Python 中的 KeyboardInterrupt 中断?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/842557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent a block of code from being interrupted by KeyboardInterrupt in Python?
提问by saffsd
I'm writing a program that caches some results via the pickle module. What happens at the moment is that if I hit ctrl-c at while the dump
operation is occurring, dump
gets interrupted and the resulting file is corrupted (i.e. only partially written, so it cannot be load
ed again.
我正在编写一个程序,通过pickle 模块缓存一些结果。目前发生的情况是,如果我在dump
操作发生时按 ctrl-c 键,则会dump
被中断并且生成的文件已损坏(即仅部分写入,因此无法load
再次编辑。
Is there a way to make dump
, or in general a block of code, uninterruptable? My current workaround looks something like this:
有没有办法让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
It seems silly to restart the operation if it is interrupted, so I am searching for a way to defer the interrupt. How do I do this?
如果操作被中断,重新启动操作似乎很愚蠢,所以我正在寻找一种推迟中断的方法。我该怎么做呢?
采纳答案by Unknown
Put the function in a thread, and wait for the thread to finish.
把函数放在一个线程中,等待线程结束。
Python threads cannot be interrupted except with a special C api.
除非使用特殊的 C api,否则无法中断 Python 线程。
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
See how the interrupt was deferred until the thread finished?
看看中断是如何推迟到线程完成的?
Here it is adapted to your use:
它适合您的使用:
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()
回答by Gary van der Merwe
The following is a context manager that attaches a signal handler for SIGINT
. If the context manager's signal handler is called, the signal is delayed by only passing the signal to the original handler when the context manager exits.
以下是为 附加信号处理程序的上下文管理器SIGINT
。如果上下文管理器的信号处理程序被调用,则只有在上下文管理器退出时才将信号传递给原始处理程序,从而延迟信号。
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()
回答by Ignacio Vazquez-Abrams
回答by Nadia Alramli
In my opinion using threads for this is an overkill. You can make sure the file is being saved correctly by simply doing it in a loop until a successful write was done:
在我看来,为此使用线程是一种矫枉过正。您可以通过简单地循环执行直到成功写入来确保文件被正确保存:
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
回答by Chris
This question is about blocking the KeyboardInterrupt
, but for this situation I find atomic file writing to be cleaner and provide additional protection.
这个问题是关于阻止KeyboardInterrupt
,但对于这种情况,我发现原子文件写入更干净并提供额外的保护。
With atomic writes either the entire file gets written correctly, or nothing does. Stackoverflow has a variety of solutions, but personally I like just using atomicwriteslibrary.
通过原子写入,要么整个文件被正确写入,要么什么都不做。Stackoverflow 有多种解决方案,但我个人喜欢只使用atomicwrites库。
After running pip install atomicwrites
, just use it like this:
运行后pip install atomicwrites
,只需像这样使用它:
from atomicwrites import atomic_write
with atomic_write(path, overwrite=True) as file:
dump(obj, file)