在包含按pickle格式存储对象的文件中查找

1 投票
2 回答
1978 浏览
提问于 2025-04-16 15:16

我有一个很大的文件,里面存储了很多对象,假设是这样:

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模块。

撰写回答