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

Python 为什么不使用pickle而不是struct?,python,struct,pickle,Python,Struct,Pickle,我无法理解pickle模块与struct模块的用法。两者都将Python对象转换为字节流。使用pickle似乎比打包和解包struct模块更容易。因此,何时使用pickle以及何时使用struct,pickle主要用于保存数据当前状态的检查点,以便其他Python进程可以使用它。它很方便,因为您不必关心要序列化的内容,因为pickle处理类实例、共享元素和递归数据结构等 Struct相反,总是附带一个协议,它是一个描述,定义了如何读取数据,没有它,您就无法解压缩数据 顺便说一句,这些库不是唯一转

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

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

Struct
相反,总是附带一个
协议
,它是一个
描述
,定义了如何读取数据,没有它,您就无法解压缩数据


顺便说一句,这些库不是唯一转储/序列化数据的库,有些方法有一个很好的总结:

,因为它们做的事情完全不同

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

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

TL/DR问题不在于性能(即使某些转换可能比其他转换稍微消耗更多的资源),而在于序列化的目标是什么:本地备份的pickle,外部交换的struct

我认为您对struct的功能有误解

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

它用于构造符合协议标准的(二进制)文件。例如,如果您有一个三维模型,那么您可能希望将导出器写入。此格式遵循特定协议(例如,它将以
0x4d4d
开头)。您不能使用pickle转储为这种格式,因为pickle实际上是一个特定的协议

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

泡菜 另一方面,Pickle是一种设计用于将Python对象存储在二进制流中的工具,这样我们可以在需要时将这些对象加载回。它定义了一个协议。例如,pickle总是以字节
128
开始流,然后是协议版本(
1
2
3
)。下一个字节指定要pickle的对象类型的标识符(例如,整数为
75
,字符串为
88
,等等)

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

d = {}
e = {'a': d}
d['a'] = e
然后我们不能简单地序列化
d
,并将
e
序列化为
e
的一部分。我们必须跟踪我们已经序列化了
d
,因为序列化
e
会导致序列化
d
,等等,直到我们的内存耗尽


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

因为pickle比较臃肿,而且有时输出流必须遵循特定的协议。许多好的问题都会根据专家经验产生一定程度的意见,但这个问题的答案往往几乎完全基于意见,而不是事实、参考资料或特定的专业知识。是吗你只说字符串流、元组或其他可序列化的结构?@Lissy:这两种结构并不等价。JSON默认情况下只能序列化普通对象,例如,它也不能检测两个变量引用同一个对象。如果存在循环依赖项,它将出错(而pickle跟踪它已pickle的对象,并创建一个反向引用)。