我这样做的方式:
将实际处理代码放入一个类中,然后在该类上实现 Pickle 协议(http://docs.python.org/library/pickle.html)(基本上,编写正确的__getstate__
函数__setstate__
)
此类将接受文件名、保留打开的文件和 CSV 阅读器实例作为实例成员。该__getstate__
方法将保存当前文件位置,setstate 将重新打开文件,将其转发到正确的位置,并创建一个新的阅读器。
我会在一个__iter__
方法中执行实际的工作,在处理每一行之后都会向外部函数屈服。
这个外部函数将运行一个“主循环”监控输入的中断(套接字、键盘、文件系统上特定文件的状态等)——一切都很安静,它只会调用处理器的下一次迭代。如果发生中断,它会将处理器状态腌制到磁盘上的特定文件。
启动时,程序只需检查是否有保存的执行,如果有,使用 pickle 检索执行器对象,并恢复主循环。
这里有一些(未经测试的)代码 - iea 很简单:
from cPickle import load, dump
import csv
import os, sys
SAVEFILE = "running.pkl"
STOPNOWFILE = "stop.now"
class Processor(object):
def __init__(self, filename):
self.file = open(filename, "rt")
self.reader = csv.reader(self.file)
def __iter__(self):
for line in self.reader():
# do stuff
yield None
def __getstate__(self):
return (self.file.name, self.file.tell())
def __setstate__(self, state):
self.file = open(state[0],"rt")
self.file.seek(state[1])
self.reader = csv.reader(self.File)
def check_for_interrupts():
# Use your imagination here!
# One simple thing would e to check for the existence of an specific file
# on disk.
# But you go all the way up to instantiate a tcp server and listen to
# interruptions on the network
if os.path.exists(STOPNOWFILE):
return True
return False
def main():
if os.path.exists(SAVEFILE):
with open(SAVEFILE) as savefile:
processor = load(savefile)
os.unlink(savefile)
else:
#Assumes the name of the .csv file to be passed on the command line
processor = Processor(sys.argv[1])
for line in processor:
if check_for_interrupts():
with open(SAVEFILE, "wb") as savefile:
dump(processor)
break
if __name__ == "__main__":
main()