Python序列化 - 为什么选择pickle?

100

我了解到Python pickling是一种将Python对象以一种符合面向对象编程的方式“存储”的方法——不同于写入文本文件或数据库的输出。

您是否有关于以下问题的更多详细信息或参考资料:

  • pickled对象存储在哪里?
  • 为什么pickling比存储在数据库中保留对象表示更好?
  • 我能从一个Python shell会话检索pickled对象到另一个会话吗?
  • 您是否有重要的示例,说明序列化很有用?
  • 使用pickle进行序列化是否意味着数据“压缩”?

换句话说,我正在寻找有关pickling的文档-Python.doc解释了如何实现pickle,但似乎没有深入探讨序列化的用途和必要性。


我的猜测是为了以后恢复状态或将对象共享/复制到不同的Python运行时。 - synthesizerpatel
14
许多关于序列化的问题都可以在维基百科的文章中找到答案:http://en.wikipedia.org/wiki/Serialization - NPE
5
你是在询问我为什么需要在Python中使用Pickle进行序列化,还是在问什么是(序列化的)目的? - moooeeeep
也许最好提一下pickle的安全问题。可以在文档和许多SO问题中找到示例,例如此处:https://dev59.com/OV8e5IYBdhLWcg3wyM_N。 - djvg
4个回答

110

Python中的pickling是将Python对象(如列表、字典等)转换成字符流的一种方法。其思想是这个字符流包含了在另一个Python脚本中重建该对象所需的所有信息。

至于pickled信息存储的位置,通常会执行以下操作:

with open('filename', 'wb') as f:
    var = {1 : 'a' , 2 : 'b'}
    pickle.dump(var, f)

这将在 'filename' 文件中存储我们的var字典的序列化版本。然后,在另一个脚本中,您可以从此文件加载到变量中,字典将被重新创建:

with open('filename','rb') as f:
    var = pickle.load(f)

使用pickle的另一个用途是,如果您需要通过网络传输此字典(例如使用套接字之类的东西),则需要首先将其转换为字符流,然后可以通过套接字连接发送它。

此外,这里没有“压缩”可言...它只是一种从一种表示形式(在RAM中)转换为另一种表示形式(在“文本”中)的方法。

About.com有一个关于pickle的不错介绍,请点击这里


2
通常情况下,人们会使用 with open('filename') as f: ... 的方式。 - moooeeeep
4
此外,您需要使用 with open(filename, 'wb') as f: ... 才能写入文件。 - Tim Pietzcker
谢谢!这篇关于Python持久化管理的文章不错,在这里 - kiriloff
1
通常情况下,使用pickle在网络上传输字典并不是一个很好的主意(这里可能更适合使用json)。尽管在某些罕见情况下,例如multiprocessing模块中,它可能会有用。 - jfs
@J.F.Sebastian:好的,但他打开文件是为了读取而不是写入。 - Tim Pietzcker
显示剩余2条评论

39

在分布式和并行计算中,选手是绝对必要的。

假设您想要使用multiprocessing(或通过pyina跨集群节点)进行并行map-reduce,则需要确保要映射到并行资源的函数可以拾取。如果它无法拾取,您将无法将其发送到另一个进程、计算机等上的其他资源。此外,这里还有一个很好的例子。

为此,我使用dill,它可以序列化Python中几乎任何内容。当您的代码失败时,Dill还具有一些很好的工具,可帮助您了解是什么导致了拾取失败。

还有,是的,人们使用选择来保存计算状态、您的ipython会话或其他东西。您还可以扩展pickle的Pickler和UnPickler以使用bz2gzip进行压缩,如果您愿意。


0

我发现它在处理大型和复杂的自定义类时特别有用。在我想到的一个特定示例中,“收集”信息(从数据库中)以创建类已经是一半的战斗了。然后,用户可能会在运行时更改存储在类中的信息。

您可以在数据库中拥有另一组表,并编写另一个函数来遍历所有存储的内容并将其写入新的数据库表中。然后,您需要编写另一个函数来能够通过读取所有这些信息来加载保存的内容。

或者,您可以将整个类作为pickle存储到数据库中的单个字段中。然后,当您要重新加载它时,它将像以前一样全部加载回来。这可以在保存和检索复杂类时节省大量时间和代码。


-1

这是一种序列化方式。使用cPickle比pickle更快。

import pickle
##make Pickle File
with open('pickles/corups.pickle', 'wb') as handle:
    pickle.dump(corpus, handle)

#read pickle file
with open('pickles/corups.pickle', 'rb') as handle:
    corpus = pickle.load(handle)

在Python2中,cPickle比pickle更快,但在Python3中,cPickle已经被集成到pickle中,所以我们可以直接使用pickle。 - FullMetalScientist

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