如何防止代码块被 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 dumpoperation is occurring, dumpgets interrupted and the resulting file is corrupted (i.e. only partially written, so it cannot be loaded 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)

