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的对象,并创建一个反向引用)。