高级 Python 开发课程
第 章
>
第 级

序列化模块
Marshal 和 Pickle 模块

目标

前往服务站,确保通过使用 JSON 模块对文件进行格式化,从而正确存储数据。

沿着道路继续前行,我们会发现一些监测水分配和土壤质量的站点,这些数据用于开发用于未来收获的土地。为了处理数据,序列化数据是高效的做法。虽然使用 Json 可以作为一种通用解决方案,但还有一些 Python 特有的序列化方法,那就是 Marshal 和 Pickle 模块。Marshal 模块旨在通过将数据转换为二进制以实现快速的序列化/反序列化,适用于较简单的数据传输。而 Pickle 模块则较慢,但它设计用来处理更复杂的数据结构,更加灵活,适用于更大或优先级更高的数据结构。

要使用 Marshal 和 Pickle 模块,请通过编写 import marshalimport pickle 来导入它们的函数。在我们的例子中,我们将使用以下函数:

  • marshal.dumps(): 将数据序列化为二进制格式,设计以实现 Python 内部的高速运行。该函数接受一个参数,即您希望序列化的数据,但受限于基本数据类型。
  • marshal.loads(): 将二进制数据反序列化为 Python 可读取的数据类型,功能有限但执行速度快。该函数接受一个参数,即您希望反序列化的数据。
  • pickle.DEFAULT_PROTOCOL: 检查您所使用的 Python 版本中 Pickle 序列化的默认协议版本。协议会影响数据的序列化方式。
  • pickle.HIGHEST_PROTOCOL: 检查您所使用的 Python 版本中 Pickle 序列化可用的最高协议版本。协议会影响数据的序列化方式。
  • pickle.dumps(): 根据所使用的协议,将复杂的 Python 数据结构序列化为二进制格式。该函数接受两个参数,即您希望序列化的数据和您希望在序列化时使用的协议版本。
  • pickle.loads(): 将二进制数据反序列化为 Python 可读取的数据类型,在处理 Python 对象方面功能强大。该函数接受一个参数,即您希望反序列化的数据。

除了这些模块和函数之外,我们还将使用一个名为 pformat 的格式化模块,我们将通过 from pprint import pformat 导入。这使我们能够使用 pformat() 函数,该函数可以用于格式化诸如字典之类的数据结构,从而使信息展示得更清晰。

首先,走到小型监控站内标有光 X 标记的地方,并面向电脑终端。该监控站监测附近被开发用于种植作物的地形的水压和土壤状况。这里有一个名为 reading 的常量,它包含了监控站收集的 Python 数据。

创建一个名为 data 的变量,并将 marshal.dumps() 函数的返回值存入其中,同时将 reading 作为参数传入。像这样:data = marshal.dumps(reading)。使用预先编写的 display() 函数和 data 变量来查看序列化后的变量数据。

走出监控站,前往金色 X 标记处,使用 open() 函数打开门并进入办公室。走到终端前标有光 X 标记的地方,将刚刚序列化的数据进行反序列化。创建一个名为 output 的变量,将 marshal.loads() 的返回值存入其中,并将之前的 data 变量作为参数传入。使用 write() 函数,并添加 output 作为参数,以访问你从监控站收集到的序列化数据。

走到办公室蓝色地毯上标有光 X 标记的地方,在终端上我们将验证协议,以确定 Pickle 模块在处理数据时将使用哪种类型的序列化。在预先编写的 write() 函数中,将参数设置为 pickle.DEFAULT_PROTOCOLpickle.HIGHEST_PROTOCOL。这将验证当前的序列化协议以及此时可用的最新序列化协议。

前往蓝色地毯上标有暗 X 标记的地方,现在既然我们已经确认了协议,我们就可以验证存储的数据。数据已在数月内收集并存储在名为 samples 的常量中。创建三个变量,分别命名为:sereal_0sereal_2sereal_5,用以验证三种可用于序列化的协议。协议 0 是可读的 ASCII 格式,但效率不高;协议 2 是一种更高效的二进制格式;而协议 5 则是最新的,具备最复杂的功能。

我们将存储 pickle.dumps() 的返回值,并将 sample 常量以及与变量名中数字对应的 protocol 作为参数传入。例如,对于 sereal_0,我们将把 protocol 设置为 0,如下所示:sereal_0 = pickle.dumps(samples, protocol=0)。使用预先编写的 display() 函数,结合 sereal_0sereal_2sereal_5,以验证各协议序列化的区别。

走到红色地毯上标有光 X 标记的地方,面向终端,覆盖 output 变量,并将 pickle.loads() 的返回值存入其中,同时将参数设置为 sereal_5,以反序列化到目前为止收集的样本数据。使用 display() 函数,并添加 pformat() 函数与 output 变量,以查看数据。像这样:await player.display(pformat(output))。记录下终端中显示的每个月的评分,以便稍后绘制图表。

走到红色地毯上标有暗 X 标记的地方,面向桌子,在预先编写的 write() 函数中,添加之前在终端中显示的每个月的评分(按字符串格式,用 "" 括起,并按函数中规定的正确顺序)。完成后即可通过此关卡。

代码书