3

我知道这并不完全是 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?(在这种情况下,为什么要让我做 mode='ba'?)有没有更简单的方法来做到这一点?

4

2 回答 2

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当你完成解封时,只需抓住告诉你。

于 2010-05-18T14:20:43.653 回答
4

答案是它确实有效,但是如果没有“+”模式,open 的附加功能自动添加的换行符会将二进制文件与字符串数据混合在一起(绝对禁止)。更改此行:

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)

Alex 还指出,为了获得更大的灵活性,请使用 mode='r+b',但这需要适当的搜索。由于我想创建一个行为类似于先进后出的 Python 对象序列的历史文件,因此尝试在文件中附加对象实际上是有意义的。我只是做得不对:)

无需单步执行该文件,因为(呃!)它是序列化的。所以替换:

for l in f:
    lst.append(pickle.loads(l))

while 1:
    try:
        lst.append(pickle.load(f))
    except IOError:
        break
于 2010-05-19T07:49:49.527 回答