我知道这并不是打算如何使用pickle模块,但我认为这会有效。我正在使用Python 3.1.2
以下是背景代码:
import pickle
FILEPATH='/tmp/tempfile'
class HistoryFile():
"""
Persistent store of a history file
Each line should be a separate Python object
Usually, pickle is used to make a file for each object,
but here, I'm trying to use the append mode of writing a file to store a sequence
"""
def validate(self, obj):
"""
Returns whether or not obj is the right Pythonic object
"""
return True
def add(self, obj):
if self.validate(obj):
with open(FILEPATH, mode='ba') as f: # appending, not writing
f.write(pickle.dumps(obj))
else:
raise "Did not validate"
def unpack(self):
"""
Go through each line in the file and put each python object
into a list, which is returned
"""
lst = []
with open(FILEPATH, mode='br') as f:
# problem must be here, does it not step through the file?
for l in f:
lst.append(pickle.loads(l))
return lst
现在,当我运行它时,它只打印出传递给该类的第一个对象。
if __name__ == '__main__':
L = HistoryFile()
L.add('a')
L.add('dfsdfs')
L.add(['dfdkfjdf', 'errree', 'cvcvcxvx'])
print(L.unpack()) # only prints the first item, 'a'!
这是因为它看到了早期的EOF吗?也许追加仅适用于ascii? (在这种情况下,为什么让我做模式='ba'?)有没有更简单的方法来做到这一点?
答案 0 :(得分:6)
为什么你认为附加二元泡菜会产生一个泡菜?! Pickling让你可以一个接一个地放入(并取回)几个项目,所以显然它必须是一个“自我终止”的序列化格式。忘记线条,让它们回来!例如:
>>> import pickle
>>> import cStringIO
>>> s = cStringIO.StringIO()
>>> pickle.dump(23, s)
>>> pickle.dump(45, s)
>>> s.seek(0)
>>> pickle.load(s)
23
>>> pickle.load(s)
45
>>> pickle.load(s)
Traceback (most recent call last):
...
EOFError
>>>
抓住EOFError
告诉你什么时候完成破坏。
答案 1 :(得分:4)
答案是它可以正常工作,但是如果没有“+”模式,则通过open的append功能自动添加的换行符将二进制文件与字符串数据混合在一起(明确禁止 - 否)。改变这一行:
with open(FILEPATH, mode='ab') as f: # appending, not writing
f.write(pickle.dumps(obj))
到
with open(FILEPATH, mode='a+b') as f: # appending, not writing
pickle.dump(obj, f)
亚历克斯还指出,为了更灵活,使用mode ='r + b',但这需要适当的搜索。由于我想创建一个历史文件,其行为类似于先入后推式的pythonic对象序列,因此我尝试在文件中追加对象实际上是有意义的。我只是没有正确地做到这一点:)
没有必要单步执行该文件,因为(duh!)它是序列化的。所以替换:
for l in f:
lst.append(pickle.loads(l))
与
while 1:
try:
lst.append(pickle.load(f))
except IOError:
break