Pickle和Shelve有什么区别?


74

我是第一次学习对象序列化。我尝试阅读和“搜索”模块中腌制和搁板的差异,但是我不确定我是否理解。什么时候使用哪个?Pickle可以将每个python对象转换为字节流,这些字节流可以保存到文件中。那为什么我们需要搁置模块呢?泡菜不是更快吗?


泡菜就像是一种非常低级的东西,而搁置为我们提供了更多存储复杂对象的方式吗?
zubinmehta 2010年

1
shelve提供一个字典样式的腌制界面。酸洗的字典接口可方便地实现诸如结果缓存(这样您就无需进行重新计算)之类的事情了-键是键*args,**kwds,值是计算结果。
Mike McKerns 2014年

1
请注意,shelve 请勿启用不能存储pickle无法腌制的对象的功能。如果您正在寻找一个更好的版本shelve,它既可以存储大多数python对象,又可以为磁盘或数据库提供更灵活的字典接口……那么您可能要看一下klepto。请参阅:stackoverflow.com/a/32586980/2379433
Mike McKerns 2015年

Answers:


94

pickle 用于将一个或多个对象序列化为文件中的单个字节流。

shelvepickle序列化字典的基础上构建并实现该序列化字典,在该序列化字典中,腌制对象但与键(某个字符串)相关联,因此您可以加载搁置的数据文件并通过键访问腌制对象。如果要序列化许多对象,这可能会更方便。

这是两者之间用法的一个例子。(应该在最新版本的python 2.7和python 3.x中工作)。

pickle

import pickle

integers = [1, 2, 3, 4, 5]

with open('pickle-example.p', 'wb') as pfile:
    pickle.dump(integers, pfile)

这会将integers列表转储到名为的二进制文件中pickle-example.p

现在尝试回读腌制的文件。

import pickle

with open('pickle-example.p', 'rb') as pfile:
    integers = pickle.load(pfile)
    print integers

以上应该输出[1, 2, 3, 4, 5]

shelve

import shelve

integers = [1, 2, 3, 4, 5]

# If you're using Python 2.7, import contextlib and use
# the line:
# with contextlib.closing(shelve.open('shelf-example', 'c')) as shelf:
with shelve.open('shelf-example', 'c') as shelf:
    shelf['ints'] = integers

注意如何通过类似字典的访问将对象添加到货架。

用如下代码重新读取对象:

import shelve

# If you're using Python 2.7, import contextlib and use
# the line:
# with contextlib.closing(shelve.open('shelf-example', 'r')) as shelf:
with shelve.open('shelf-example', 'r') as shelf:
    for key in shelf.keys():
        print(repr(key), repr(shelf[key]))

输出将是'ints', [1, 2, 3, 4, 5]


您能否阐明调用中的“ c”标志是shelve.open什么?我用谷歌搜索,但找不到答案。提前致谢。
aniketd

7
@aniketd'c'标志指示shelve打开文件以进行读取或写入,或者根据需要创建文件。shelve.open的文档中也对此进行了描述,该文档与共享相同的标志anydbm.open
wkl 2015年

@birryree您的示例使用哪个版本的Python?在2.7.10上,这表明没有实现任何搁置的Context Manager:----> 5 with shelve.open('shelf-example-file.txt', 'c') as shelf: 6 for k, v in my_dict: 7 shelf[k] = v AttributeError: DbfilenameShelf instance has no attribute '__exit__'
Pyderman

@Pyderman我必须已经在3.x而不是2.7.x中验证了我的代码,可能假设上下文管理器的用法在它们之间没有什么不同。我更新了示例,说如果您使用的是Python 2.7,则应import contextlib在代码中shelve.open加上contextlib.closing()
wkl

该问题将从以下内容中受益:关于何时选择哪种
口味

3

根据泡菜文档:

序列化是比持久性更原始的概念。尽管pickle可以读写文件对象,但是它不能处理持久对象的命名问题,也不能解决并发访问持久对象的问题(甚至更复杂)。所述泡菜模块可以将一个复杂的对象成字节流,它可以改造字节流成一个对象具有相同的内部结构。也许与这些字节流有关的最明显的事情是将它们写入文件,但是也可以考虑通过网络发送它们或将它们存储在数据库中。该货架模块提供了一个简单的界面,咸菜和unpickle对象上DBM风格的数据库文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.