Python 为什么';添加二元泡菜不行吗?
我知道这并不是pickle模块的预期用途,但我认为这会起作用。我正在使用Python 3.1.2 以下是背景代码:Python 为什么';添加二元泡菜不行吗?,python,pickle,Python,Pickle,我知道这并不是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 m
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?(在这种情况下,为什么它允许我执行mode='ba'?)有更简单的duh方法来执行此操作吗?为什么您认为附加二进制pickle会产生单个pickle?!pickle允许您一个接一个地放置(并取回)多个项,因此显然它必须是一种“自终止”序列化格式。忘记台词,把它们拿回来!例如:
>>> 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
来告诉您何时完成取消勾选。答案是它确实可以工作,但如果没有模式中的“+”,则由open的append功能自动添加的换行符会将二进制与字符串数据混在一起(明确的否)。更改此行:
with open(FILEPATH, mode='ab') as f: # appending, not writing
f.write(pickle.dumps(obj))
到
Alex还指出,要获得更大的灵活性,请使用mode='r+b',但这需要进行适当的搜索。因为我想创建一个历史文件,它的行为类似于Python对象的先入后出序列,所以我尝试在文件中添加对象是有意义的。我只是做得不对:)
不需要单步遍历该文件,因为它是序列化的。因此,请替换:
for l in f:
lst.append(pickle.loads(l))
与
我不知道pickle模块,我的python I/O有点生疏,但我的猜测是,您可能正在从文件中读取行,而对象存储时没有换行符分隔(实际上,可能包含换行符,所以如果是这样的话,您可能想更改),是的,但类必须打开文件以获得写权限,这会删除文件。我想保留它。这就是为什么我想附加这个文件。那么,在开始写作之前阅读内容的标准做法是什么呢?@Adam,只需使用
'r+'
(或者更好的'r+b',这样你就可以使用pickle.HIGHEST_protocol
的协议进行选择!),cfr和@Alex得到了它;谢谢在公开赛中,我没有对+给予足够的关注。真的很简单。但是仍然不确定最高的_协议是什么,在python3中,他们推荐协议3,这是默认的@Adam,HIGHEST\u PROTOCOL
,又名-1
,意思是“你能做的最好”,并且是你应该一直使用的,除非你需要你的pickle可以被旧版本的Python加载。在Python2.*中,默认值是0(ascii协议),因此它必须保持向后兼容性——就像在Python3中必须保持3.*永远如此,即使明天有人发明了一种占用一半时间和空间的新格式(我知道不太可能;-)。因此,如果您不想制作可供较旧Python版本读取的pickle,请始终使用-1!)只是尝试了一下,mode='r+b'似乎不起作用。看了看文档,现在理解得更好了,我尝试了“a+b”,效果和预期一样。我知道pickle不是这样构思的,但事实证明,您可以向文件写入一系列pickle项!
for l in f:
lst.append(pickle.loads(l))
while 1:
try:
lst.append(pickle.load(f))
except IOError:
break