为什么不使用pickle而不是struct?

时间:2018-01-06 11:01:26

标签: python struct pickle

我无法理解pickle模块与struct模块的使用。两者都将Python对象转换为字节流。使用pickle比使用struct模块的打包和解包更容易。那么何时使用pickle以及何时使用struct

3 个答案:

答案 0 :(得分:5)

我认为你对struct的作用有误解。

STRUCT

Struct 意味着将 Python 对象存储到字节流中。它的作用是通过 对象转换为结构来生成字节流,结构表示包含的对象的数据。例如,对整数使用带符号的32位表示。但是struct例如设计用于存储字典,因为有很多方法可以序列化字典。

它用于构造满足协议标准的(二进制)文件。例如,如果您有一个3d模型,那么您可能想要将导出器写入.3ds file format。此格式遵循特定协议(例如,它将以0x4d4d开头)。你不能使用pickle转储到这种格式,因为Pickle实际上是一个特定的协议。

将二进制文件读入Python对象也一样。您无法在.3ds文件上运行Pickle,因为Pickle 知道协议。它不知道文件开头的0x4d4d是什么意思。它可以是一个16位整数(19789),它可以是一个2字符的ASCII字符串('MM')等。通常大多数二进制文件都是为一个目的而设计的。你需要了解它 protocol 以读取/写入此类文件。

味酸

另一方面,Pickle是一个用于在二进制流中存储 Python对象的工具,这样我们可以在需要时将这些对象加载回来。它定义了一个协议。例如,pickle始终使用字节128启动流,然后是协议版本(123)。下一个字节指定了我们要选择的对象类型的标识符(例如,对于整数,75,对于字符串,88,等等。

Pickle还必须序列化对象的所有引用,并跟踪它已经序列化的对象,因为它可以有循环结构。例如,如果我们有两个词典:

d = {}
e = {'a': d}
d['a'] = e

然后我们不能简单地序列化d,并将e序列化为e的一部分。我们必须跟踪已经序列化d,因为序列化e会导致序列化d等,直到我们的内存不足为止。

因此,Pickle是存储 Python 对象的特定协议。但是我们不能用它来序列化为特定的格式,这样其他(非Python)程序就可以读取它。

答案 1 :(得分:3)

因为他们做了很多不同的事情。

您可以通过不同方式序列化对象:

  • 文本序列化格式:此处序列化对象是人类可读的。常见格式为json和xml,或csv用于简单的列表。但除了非常简单的对象(数组,字典和简单数据)之外,您需要定义编组协议以保存对象的相关部分,然后从其序列化版本重建对象
  • 二进制序列化格式:
    • pickle旨在自动序列化一个对象,并允许它自动反序列化,前提是该类在反序列化时可用。它的主要缺点是它只能用于Python
    • struct恰恰相反:您必须专门决定保存的内容和格式。在反序列化时,您还必须知道使用的格式。但它可用于与任何其他语言交换二进制流,前提是格式明确定义

TL / DR问题与性能无关(即使某些转换可能比其他转换的资源消耗略多)但更多的是序列化的目标:本地备份的pickle ,struct for外部交流

答案 2 :(得分:0)

Pickle主要用于保存数据当前状态的checkpoint,以便某些其他Python Process可以使用它。这很方便,因为您不必关心必须序列化的内容,因为pickle处理类实例,共享元素和递归数据结构等等。

相反,

Struct总是带有一个protocol description,它定义了如何读取数据,没有它,你就无法解压缩数据。

顺便说一下。那些不是转储/序列化数据的唯一库,有一些方法的总结很好:http://effbot.org/librarybook/data-representation-index.htm