在包含按pickle格式存储对象的文件中查找
我有一个很大的文件,里面存储了很多对象,假设是这样:
for object in objects:
pickle.dump(myfile,object)
这些对象虽然是同一种类型,但大小各不相同。
这个文件会在不同的时间被不断填充,但有时候,当我重新开始写入时,我需要读取最后几个对象。
大概是这样的:
myfile.seek(-1000,2)
while myfile.tell() < mysize:
objects.append(pickle.load(myfile))
现在,这显然不行,因为-1000通常不会出现在某个对象的开头,这样pickle就会报错等等。
虽然我可以用try except: pass的方式,让pickle一直尝试,直到找到可以读取的对象,但我不太喜欢这个主意。我怀疑这样做会让文件指针在某些读取尝试中移动得太远,可能会错过一些对象。
从头开始读取文件是不现实的,因为文件太大了。
有没有什么办法可以解决这个问题?有没有方法让pickle检查当前的文件指针是否指向一个看起来像对象的地方?
2 个回答
0
保存每次更新文件后,文件大小增加的序列,可以放在任何地方。
3
一种方法是这样做:
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模块。