高级 Python 开发课程
第 章
>
第 级
序列化模块
Marshal 和 Pickle 模块
目标
前往服务站,使用 JSON 模块格式化文件,以确保数据得到正确存储。
沿着小路继续前进,我们会发现几个监测水分分布和土壤质量的站点,这片土地正在为未来的收获而开发。为了处理这些数据,序列化是一种高效的方法。虽然使用 JSON 作为通用解决方案很有效,但也有一些 Python 特定的序列化方法,即 Marshal 和 Pickle 模块。Marshal 模块通过将数据转换为二进制来实现快速的序列化/反序列化,适用于简单的数据传输。Pickle 模块虽然较慢,但它能够处理更复杂的数据结构,并且更具灵活性,适用于更大或更优先的数据结构。
要使用 Marshal 和 Pickle 模块,请通过编写 import marshal 和 import 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_PROTOCOL 和 pickle.HIGHEST_PROTOCOL。这将验证当前的序列化协议以及此时可用的最新序列化协议。
继续前往蓝地毯上的暗色 X 标记处,现在我们已经确认了协议,可以开始验证存储的数据。数据已经在几个月内被收集并存储在名为 samples 的常量中。创建三个变量:sereal_0、sereal_2 和 sereal_5,我们将用它们来验证三种可用的序列化协议。协议 0 是可读的 ASCII,不太高效;协议 2 是更高效的二进制格式;协议 5 是最新的,具有最复杂的功能。
我们将调用 pickle.dumps() 并传入 samples 常量和与变量名中数字对应的 protocol。例如,对于 sereal_0,将 protocol 设置为 0,如下所示:sereal_0 = pickle.dumps(samples, protocol=0)。然后使用预先编写的 display() 函数分别传入 sereal_0、sereal_2 和 sereal_5,以验证不同协议下序列化的差异。
走到红地毯上的亮色 X 标记处,面对终端,重写 output 变量,并将 pickle.loads() 的返回值赋给它,传入 sereal_5 作为参数,以反序列化迄今为止收集的样本数据。使用 display() 函数,并结合 pformat() 函数处理 output 变量以查看数据,如:await player.display(pformat(output))。记下终端中显示的每个月的评分,以便稍后绘制图表。
走到红地毯上的暗色 X 标记处,面对书桌,在预先编写的 write() 函数中,添加之前在终端中记录的每个月评分。按照函数中所示的正确顺序将它们以带双引号 "" 的字符串形式添加,以完成本关卡。