特殊功能运行完毕后中止python脚本

时间:2016-06-10 07:12:35

标签: python python-3.x

我有一个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)

3 个答案:

答案 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)

您想保护两项操作:

  1. 您的数据更新(不一定是计算)
  2. 一旦CTRL + C被点击,您的数据就会被写入
  3. 仅使用tryexcept块,这些都可以简单地中断并使您的数据或输出文件处于损坏状态。

    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)