我有一个python脚本,它具有很长的运行时间。 有时我需要中止并稍后运行它。它将当前结果转储到pickle文件中,但在文件被损坏的错误时间中止(CTLR + C)。
有没有办法让脚本完成该任务并在之后中止? 我不知道在哪里寻找。
谢谢
编辑:我的程序看起来有点像这样:
import pickle
for key in keylist:
do_smth(mydict)
with open('myfile.p','w+b') as f:
pickle.dump(mydict,f)
Edit2:谢谢你们,试试:......除了:......就像一个魅力。 由于我是脚本的唯一用户,因此我不需要“保存”版本。但是我肯定会调查它(现在我不熟悉线程)。
我也改变了我的循环,我只会在发生异常或循环结束后挑选我的文件。
import pickle
for key in keylist:
try:
do_smth(mydict)
except KeyboardInterrupt:
print("Saving data ...")
with open('myfile.p','w+b') as f:
pickle.dump(mydict,f)
with open('myfile.p','w+b') as f:
pickle.dump(mydict,f)
答案 0 :(得分:2)
Ctrl + C 实际上会抛出一种名为KeyboardInterrupt
的特殊异常。因此,如果您中止脚本以便稍后运行它的方式是发送该异常,则可以在退出之前保存数据。这可以通过将代码包装在try-except
块中并捕获KeyboardInterrupt
例外来完成
一个例子如下:
try:
# your main code here
except KeyboardInterrupt:
# do the saving here
exit(-1) # exit the program with the return code -1
关于评论:确保您发送此例外一次 这是因为如果您发送它,代码将转到保存部分,该部分没有异常捕获块。因此,如果您多次发送,您的数据可能会被不正确地保存。
答案 1 :(得分:2)
您想保护两项操作:
仅使用try
,except
块,这些都可以简单地中断并使您的数据或输出文件处于损坏状态。
This answer有一个有趣的评论:
除了特殊的C api之外,不能中断Python线程。
所以你可能想要做的是在你的代码中捕获KeyboardInterrupt
并在这个except
分支内,启动一个写出当前数据的线程。我举了一个例子:
import time
from threading import Thread
def heavy(n):
for i in range(10000):
time.sleep(1)
print("doing some computation")
def noInterrupt(path, obj):
try:
print("interrupted, writing out data (try to press CTRL+C again)...")
for i in range(5):
time.sleep(1)
print("...wrote block %d/5" % i)
finally:
print("DONE writing file")
mydata = []
try:
# press CTRL+C somewhere here
# manipulate data
for i in range(1000):
heavy(i)
except KeyboardInterrupt:
a = Thread(target=noInterrupt, args=("path/to/file", mydata))
a.start()
a.join()
注意:不要忘记,您的数据操作也可能因KeyboardInterrupt
而损坏,因此您可能希望确保保护更新数据的过程(使用其他线程?)
答案 2 :(得分:0)
您还可以为KeyboardInterrupt
:
import signal
import sys
def signal_handler(signal, frame):
#make sure you save the file
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)