Python序列化 - 为什么选择pickle?
我了解到,Python 的“序列化”是一种将 Python 对象“存储”的方式,这种方式遵循面向对象编程的原则,和直接写入文本文件或数据库的方式不同。
你能提供更多关于以下几点的细节或参考资料吗:
- 被序列化的对象“存储”在哪里?
- 为什么序列化能更好地保留对象的表现形式,而不是像存储在数据库中那样?
- 我可以在一个 Python 会话中序列化对象,然后在另一个会话中取出来吗?
- 你有没有一些重要的例子,说明序列化是如何有用的?
- 使用 pickle 进行序列化是否意味着数据会“压缩”?
换句话说,我在寻找关于序列化的文档——Python 的文档解释了如何实现 pickle,但似乎没有深入探讨序列化的使用和必要性。
4 个回答
我觉得在处理大型和复杂的自定义类时,这个方法特别有用。举个例子,想要从数据库中“收集”信息来创建这个类,光这一步就已经很费劲了。然后,用户在运行程序时可能会对存储在类中的信息进行修改。
你可以在数据库中再建立一组表格,然后写一个函数去遍历所有存储的信息,把它们写入新的数据库表中。接着,你还需要写另一个函数来加载保存的数据,把所有信息读回来。
另外一种方法是,你可以把整个类直接“打包”起来,然后把它存储到数据库的一个字段中。这样,当你需要加载它的时候,所有内容就会一次性恢复到之前的状态。这种方法在保存和读取复杂类的时候,可以节省很多时间和代码。
序列化在分布式和并行计算中是非常重要的。
比如说,如果你想用 multiprocessing
来进行并行的地图-归约操作(或者在集群节点之间使用 pyina),那么你需要确保你想要在并行资源上使用的函数能够被序列化。如果它不能被序列化,你就无法把它发送到其他进程、计算机等地方。你可以在 这里 找到一个很好的例子。
为了解决这个问题,我使用 dill,它几乎可以序列化 Python 中的任何东西。Dill 还提供了一些很好的工具,帮助你理解为什么你的序列化会失败,尤其是在代码出错的时候,具体可以查看 这里。
而且,没错,人们使用序列化来保存计算的状态,或者你的 ipython 会话,或者其他任何东西。如果你愿意,还可以扩展 pickle 的 Pickler 和 UnPickler 来进行压缩,比如使用 bz2
或 gzip
。
Pickling(序列化)是一种把Python对象(比如列表、字典等)转换成字符流的方法。简单来说,这个字符流里包含了重建这个对象所需的所有信息,你可以在另一个Python脚本中用它来恢复这个对象。
至于这些被序列化的信息存储在哪里,通常我们会这样做:
with open('filename', 'wb') as f:
var = {1 : 'a' , 2 : 'b'}
pickle.dump(var, f)
这样就会把我们这个var
字典的序列化版本存储在一个叫做'filename'的文件里。然后在另一个脚本中,你可以从这个文件加载数据到一个变量里,这样字典就会被重新创建:
with open('filename','rb') as f:
var = pickle.load(f)
另外,序列化还有一个用途,就是如果你需要通过网络传输这个字典(比如用套接字之类的)。你首先需要把它转换成字符流,然后就可以通过套接字连接发送它。
另外,这里并没有什么“压缩”的说法……这只是把一种表示方式(在内存中)转换成另一种表示方式(在“文本”中)。
关于序列化,About.com有一个不错的介绍,可以在这里查看。