为什么不用 pickle 而不是 struct?

Why not use pickle instead of struct?

我无法理解 pickle 模块与 struct 模块的用法。两者都将 Python 对象转换为字节流。使用 pickle 似乎比 struct 模块的打包和解包更容易。那么什么时候用pickle,什么时候用struct呢?

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

Struct 相反总是带有一个 protocol ,它是一个 description 定义如何读取数据,没有它,你不能解压数据。

顺便说一句。这些不是 dump/serialize 数据的唯一库,对一些方法有很好的总结:http://effbot.org/librarybook/data-representation-index.htm

因为他们做的事情完全不同。

您可以用不同的方式序列化对象:

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

TL/DR 问题不在于性能(即使某些转换可能比其他转换稍微消耗更多资源),但更多关于序列化 objective 的内容:本地泡菜 backups,外部交换结构

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

结构

Struct not 意味着将 Python 对象存储到字节流中。它所做的是通过 transforming Python objects 生成字节流到 structures 表示data 包含的对象。例如,对整数使用带符号的 32 位表示。但是 struct 例如 不是 旨在存储字典,因为有很多方法可以序列化字典。

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

与将二进制文件读入 Python 对象相同。您不能 运行 Pickle 覆盖 .3ds 文件,因为 Pickle 不知道 协议。它不知道文件开头的 0x4d4d 是什么意思。它可以是一个 16 位整数(19789),它可以是一个 2 个字符的 ASCII 字符串('MM'),等等。通常大多数二进制文件都是为一个目的而设计的。你需要了解协议为了read/write这样的文件。

泡菜

另一方面,

Pickle 是一种旨在将 Python 对象 存储在二进制流中的工具,以便我们可以在需要时将这些对象加载回来。它定义了一个协议。例如 pickle 总是以字节 128 开始流,后跟协议版本(123)。下一个字节指定我们要 pickle 的对象类型的标识符(例如 75 表示整数,88 表示字符串等。

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

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

那我们不能简单的序列化d,将e序列化为e的一部分。我们必须跟踪我们已经序列化 d,因为序列化 e 否则会导致序列化 d,等等,直到我们 运行 内存不足。

因此,

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