在特殊函数运行完毕后中止python脚本

2024-04-23 19:23:19 发布

您现在位置:Python中文网/ 问答频道 /正文

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

编辑2:谢谢你们,试试看:。。。除了:。。。很有魅力。 因为我是脚本的唯一用户,所以我不需要“保存”版本。不过,我肯定会调查它(现在我不熟悉线程)。在

我还更改了我的循环,我将只pickle我的文件,以防出现异常或在循环完成后。在

^{2}$

Tags: 文件方法keyinimport程序脚本编辑
3条回答

Ctrl+C实际上抛出了一种称为KeyboardInterrupt的特殊类型的异常。因此,如果中止脚本以便稍后运行它的方法是发送该异常,则可以在退出之前保存数据。{{可以通过

try:
    # your main code here
except KeyboardInterrupt:
    # do the saving here
    exit(-1)   # exit the program with the return code -1

关于注释:请确保将此异常发送一次。
这是因为如果您发送它,代码将转到保存部分,这没有异常捕获块。因此,如果您多次发送,您的数据可能保存不正确。在

您还可以为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)

您要保护两个操作:

  1. 数据更新(不一定是计算)
  2. 在按下CTRL+C之后写入数据

仅使用tryexcept块,这两个都可以被中断,并使数据或输出文件处于损坏状态。在

This answer有一个有趣的评论:

Python threads cannot be interrupted except with a special C api.

因此,您可能需要做的是在代码中捕获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破坏,因此您可能需要确保(用另一个线程?)保护更新数据的过程在

相关问题 更多 >