我有一个巨大的文件,其中pickle了对象,让我们假设:
for object in objects:
pickle.dump(myfile,object)
这些物体虽然是同一种类型,但大小不同。
在不同的情况下,文件会被填充很长时间,但有时,当转储进程重新启动时,我需要读取最后一个对象。
像这样:
myfile.seek(-1000,2)
while myfile.tell() < mysize:
objects.append(pickle.load(myfile))
现在,这显然不起作用,因为-1000通常不在一个对象的开始,并且pickle会引发异常等…虽然我可以只是尝试except:pass并让pickle失败,直到它找到可拾取的东西,但我真的不喜欢这个想法,我怀疑它确实在某些读取尝试中过多地推进了文件,并且我可能会丢失一些对象。
由于文件太大,不能从头开始读取。
有什么好主意吗?有没有什么方法可以让pickle检查当前文件游标是否指向一个看起来像对象的东西?
一种方法是这样做:
import os, pickle, struct
myfile = open('/path/to/my/file', 'w+b')
myfile.write(struct.pack('L', 0)) # write a long of zeroes
index = []
for o in objects:
index.append(myfile.tell())
pickle.dump(o, myfile)
index_loc = myfile.tell()
pickle.dump(index, myfile)
myfile.seek(0, 0, os.SEEK_SET)
myfile.write(struct.pack('L', index_loc))
现在您有了一个索引文件:当重新打开时,从初始字节读取索引位置,然后查找该位置并读取索引。然后,您应该能够以随机访问的方式访问文件中的任何对象。(当然,您可以通过将索引作为文件位置的对象键的字典来推广这一点-一种穷人的ZODB)。
当然,您也可以使用shelve模块
在任何地方保存由于更新文件而导致的每个文件大小增量的序列