第9章 序列化和保存——JSON、YAML、Pickle、CSV和XML
为了存储Python中的对象,必须先将其转换为字节,然后再将字节写入文件。这个过程称为序列化,又叫作数据转换(marshaling)、压缩(deflating)或编码(encoding)。接下来我们会介绍几种将一个Python对象转换为字符串或字节流的方式。
每种序列化方式又称为物理数据格式,每种格式各有优缺点。对于呈现对象的方式而言,没有所谓最好的格式。我们需要和逻辑数据格式区分开,它只是简单地将字节流重新排列或改变空格的使用方式,而并未改变对象的值,只是对字节流的操作。
比较重要的一点是(尤其是CSV格式),这些表达方式只是在表达一个单一的Python对象。然而这个单一的对象可以是一组对象的集合,范围是固定的。为了处理这些对象中的一个,必须对整个集合进行反序列化,完成增量序列化需要额外的工作量。不必下太多工夫在如何使用不同格式处理多个对象的序列化,第10章“用Shelve保存和获取对象”、第11章“用SQLite保存和获取对象”和第12章“传输和共享对象”会介绍更好的方式来处理多个不同的对象。
正因为这些方式中的每一个都是针对单一的对象,所以我们无法在对象集合的内存使用方面做太多的控制。当需要处理大量不同的项时,并不能一次性把它们加载到内存,我们无法直接使用这些技术。这时,就需要移至更大的数据库、服务器或消息队列中。现在我们来了解如下几种序列化的表示方式。
- JavaScript Object Notation(JSON):这是一种被广泛使用的表示方式。更多信息可以参见:http://www.json.org。json模块提供了用于加载和转储数据所需要的类与函数,都是关于json格式操作。在Python标准库中,可以看一下第19节“网络数据处理”,而不是第12节“存储”。与一般的Python对象的存储问题相比,json模块更侧重于JSON的表达方式。
- YAML不是标记语言(YAML):它是JSON的一种扩展,而且可以简化序列化结果。更多信息可参见:http://yaml.org。它并非Python库的一部分;必须引用外部的模块。在PyYaml包中,提供了很多Python的存储功能。
- pickle:pickle模块内置有Python特殊的数据表示方式。由于它是Python库中很重要的一部分,因此我们会详细地介绍如何使用这种方式来序列化对象。而当与非Python程序交互数据时,这并非一个恰当的做法。在第10章“用Shelve保存和获取对象”中,它是shelve模块的基础;同样地,在第12章“传输和共享对象”中,对象的共享和转换中的消息对象也是基于它实现的。
- Comma-Separated Values(CSV)模块:在表达复杂的Python对象时,这种格式显得不够方便。由于它的使用很普遍,因此需要找到将Python对象序列化为CSV的方案。可以参考Python标准库中的第14节“文件格式”,而非第12节“存储”。因为它是一种简单的文件格式,或者稍微复杂一些。使用CSV格式,可以在不必一次性加载到内存的前提下进行Python对象集合的增量表示。
- XML:虽然有一些缺陷,但它很常用,因此将对象转换为XML格式,以及从XML文件中反序列化至对象是很重要的操作。而XML解析这个主题太大,可参见Python标准库中的第20节“结构化标记处理工具”。有很多模块可用来解析XML,但每种各有优缺点,我们会重点关注ElementTree。
除了以上几种简单的分类,还会遇到混合使用的情形。一个例子是以XML格式编码的电子数据表。这意味着存在两个子问题,一个是行列数据的表示,另一个是XML解析的问题。这导致了需要使用更复杂的软件来将不同数据格式转换为类似CSV的行,用于完成Python对象的转换。在第12章“传输和共享对象”和第13章“配置文件和持久化”中会再次对这类主题进行回顾,如何使用RESTful的Web服务和序列化对象,以及配置文件和可编辑的序列化对象。
