什么是pickle在做什么?

6

我已经使用Python好几年了。我广泛使用pickle。但是我无法弄清楚这个代码段的作用:

with codecs.open("huge_picklefile.pc", "rb") as f:
    data = pickle.load(f)
    print(len(data))
    data = pickle.load(f)
    print(len(data))
    data = pickle.load(f)
    print(len(data))

这会将其返回给我:

335
59
12

我很困惑。我习惯将大文件用pickle加载到内存中。对象本身是一个巨大的数组,可能由多个pickle对象组成。它可能由多个pickle对象组成吗?不幸的是,我没有创建pickle对象的权限,也不知道谁创建了它。
我无法确定为什么pickle会将我的文件分成多个块,这不是默认设置,而且我也没有告诉它这样做。重新加载相同的文件会发生什么?直到现在,我从未尝试过或遇到过这种情况。
我花了5个小时的时间试图在Google上发问这个问题,但结果并不太有用。Python 3.7 pickle文档没有描述这种行为。我无法弄清楚重复加载pickle文档如何既不崩溃又不将整个文档加载到内存中,然后只引用自己。在我15年的使用Python的经验中,我从未遇到过这个问题…所以我认为这很奇怪,我们应该改为使用数据库。

不确定这是否有效,但通过查看Python 3.7 Pickle的文档,答案可能是调用pickle.load(f, *)一次性加载所有对象文件? - Max Collier
1
@MaxCollier:这不是有效的语法。我认为你误读了函数签名。函数签名中的 * 指定了关键字参数的开始位置。你不能将 * 作为参数传递给函数。 - user2357112
pickle will load one object at a time. there may be further serialized objects if someone has done pickle.dump(f, obj) ob the file to create it. Some people do this, for some odd reason. I suppose, it is easy to serialize various objects and read them in and process them lazily this way, but it is likely better to use something like shelve - juanpa.arrivillaga
1个回答

5
这个文件不是一个标准的pickle文件。有人将多个pickle对象倒入到同一个文件中,导致文件内容是多个pickle对象的串联。当你调用pickle.load(f)时,pickle会从当前文件位置开始读取文件,直到找到pickle对象的结尾为止,所以每次pickle.load调用都会加载下一个pickle对象。
你可以通过反复调用pickle.dump来创建这样的文件:
with open('demofile', 'wb') as f:
    pickle.dump([1, 2, 3], f)
    pickle.dump([10, 20], f)
    pickle.dump([0, 0, 0], f)

我相信这是pickle设计的一部分,但无论如何,对于这种情况,应该使用shelve - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接