序列化处理——测试工程师Python开发实战(16)

发表于:2023-8-31 10:01

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:胡通    来源:51Testing软件测试网原创

#
Python
  4.12  序列化处理
  当两个进程进行网络通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等,这些数据都会以二进制序列的形式在网络上传送。当发送方需要把一个Python对象转换为字节序列,然后在网络上传送,这就是序列化;当接收方需要从字节序列中恢复Python对象,这就是反序列化。序列化和反序列化主要有两个作用。
  (1)便于存储。序列化过程将文本信息转换为二进制数据流。信息就容易存储在硬盘之中,当需要读取文件时,系统从硬盘中读取数据,然后再将其反序列化便可以得到原始的数据。如果想要长久地保存Python程序运行中得到的一些字符串、列表、字典等数据,方便以后使用,则不能简单地将数据放入内存中,然后关机断电,这将丢失数据。
  (2)便于传输。两个进程在进行远程通信时,可以互相发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个数据对象转换为字节序列,接收方则需要把字节序列恢复为数据对象。
  4.12.1  序列化和反序列化方法
  现在,大多数项目既不是单机的,也不是单服务的,需要多个程序配合,通过网络将数据传送到其他节点,这就需要大量的序列化、反序列化过程。
  Python程序之间可以使用pickle库解决序列化和反序列化问题,如果是跨平台、跨语言或跨协议,那么pickle库就不太适合了,这就需要公共的协议,如JSON、msgpack等。不同的协议传送效率不同,我们要根据不同的场景和需求分析选型。
  本节主要讲解pickle、JSON和msgpack这3个库。
  4.12.2  pickle库
  pickle库只能用于Python,并且不同Python版本之间不兼容,因此,建议pickle库只用于保存那些不重要的数据。pickle库提供了4个方法:dumps()、dump()、loads()和load()。其中,序列化的方法为dump()和dumps(),如表4-30所示。
表4-30  pickle库的序列化方法
  示例如下:
[{'a': 'A', 'b': 2, 'c': 2.22}]
b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\
x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x01\xc2\x8f\\(\xf5\xc3ua.'
  输出结果如下:
import pickle
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
  dumps()方法可以接受一个可省略的protocol参数,默认值为0。protocol参数值不同,表示进行的编码协议不同,得到的data_string也不同。
  另外,如果需要保存为文件,如data.pkl,可以使用dump()方法,示例如下:
  虽然使用pickle库序列化的字符串不一定可读,但是我们可以用pickle.loads()方法来从这个字符串中恢复原对象的内容(load string)。也就是说,dumps()方法和loads()方法有相反的作用,如表4-31所示。
表4-31  pickle库的反序列化方法
  示例如下:
pickle.loads(data_string)
  输出结果如下:
[{'a': 'A', 'b': 2, 'c': 2.22}]
  注意,pickle库只能用于Python程序,用其他语言去解析Python程序序列化存储的文本文件是会产生问题的。我们在使用pickle库时,要注意dumps()方法与loads()方法、dump()方法与load()方法的使用区别,dumps()方法和dump()方法是在内存中操作的,loads()方法和load()方法是在文件中操作的。pickle库是以字节来进行序列化的,调用dumps()方法和dump()方法的时候还可以传入参数protocol和fix_imports。
  4.12.3  json库
  JSON是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言,易于我们阅读和编写,也易于机器解析和生成,可以有效地提升网络传输效率。
  json库也提供了4个常用的方法:dumps()、dump()、loads()和load(),用于字符串和Python数据类型间进行转换。
  json.dumps(obj)将Python数据对象obj转化为JSON格式;
  json.loads(str)将JSON数据转换为Python的数据;
  json.dump(obj, fp)将Python数据对象转换为JSON格式并保存到文件中;
  json.load(fp)从文件中读取JSON格式,并转化为Python数据对象。
  示例如下:
import json
my_dict = {'a':'1','b':'2','c':'3','d':'4'}
print(type(my_dict))
a = json.dumps(my_dict)
print(a)
print(type(a))
b=json.loads(a)
print(b)
print(type(b))
  输出结果如下:
<class 'dict'>
{"a": "1", "b": "2", "c": "3", "d": "4"} #JSON字符串是以双引号显示。
<class 'str'> 
{'a': '1', 'b': '2', 'c': '3', 'd': '4'}
<class 'dict'>
  如果在使用dumps()方法时有中文字符,建议添加参数设置ensure_ascii=False,避免乱码。
  提示
  在日常使用Python的过程中,我们会经常遇到JSON格式的数据,尤其是嵌套结构复杂的JSON数据,从中抽取键值对数据的工作十分繁杂。我们知道,对于XML格式的具有层次结构的数据,可以通过xpath语句来灵活地提取满足某些结构规则的数据。
  类似地,JSONPath是用于从JSON数据中按照层次规则抽取数据的一种实用工具,在Python中我们可以使用jsonpath库来实现JSONPath的功能。jsonpath是一个第三方库,可以用来提取具有较深且复杂的嵌套层次的JSON数据,为了满足日常提取数据的需求,JSONPath中包含一系列语法规则来实现对目标值的定位,十分便捷。
  4.12.4  msgpack库
  msgpack是一个高效的基于二进制的对象序列化类库,可用于跨语言通信。它可以像JSON一样,在许多种语言之间交换结构对象。但是它比JSON使用起来更快速、轻巧,并支持Python、RubyJava、C/C++等众多语言。
  msgpack库不是Python的内置库,因此通常用pip进行安装,命令为pip install msgpack-python。msgpack库提供了如下4个常用方法。
  packb()方法用于序列化对象,提供了dumps()方法来兼容pickle库和json库。
  unpackb()方法用于反序列化对象,提供了loads()方法来兼容pickle库和json库。
  pack()方法用于序列化对象保存到文件对象,提供了dump()方法来兼容pickle库和json库。
  unpack()方法用于将反序列化对象保存到文件对象,提供了load()方法来兼容pickle库和json库。
  示例如下:
import msgpack
v = msgpack.packb([1, 2, 3], use_bin_type=True)
  输出结果如下:
'\x93\x01\x02\x03'
  示例如下:
msgpack.unpackb(v, raw=False)
  输出结果如下:
[1, 2, 3]
  3种序列化方式的对比如代码清单4-13所示。
# -*- coding: utf-8 -*-
# @Time : 2022/3/2 11:29 上午
# @Project : Demo
# @File : compare.py
# @Author : hutong
# @Describe: 微信公众号: 大话性能
# @Version: Python3.9.8
?
import json
import pickle
import msgpack
json_object = {'name': 'Tom', 'age': 20, 'interest': ('music', 'movie'), 'class': ['Python']}
?
# pickle库
data = pickle.dumps(json_object)
print(type(data), len(data), data)  # 86 bytes
?
# json库
data = json.dumps(json_object)
print(type(data), len(data), data)  # 79 bytes
print(len(data.replace(' ','')))
?
# msgpack库
data = msgpack.dumps(json_object)
print(type(data), len(data), data)   # 51 bytes
代码清单4-13  compare
  输出结果如下:
<class 'bytes'> 86 b'\x80\x04\x95K\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03Tom\x94\x8c\x03age\x94K\x14\x8c\x08interest\x94\x8c\x05music\x94\x8c\x05movie\x94\
x86\x94\x8c\x05class\x94]\x94\x8c\x06Python\x94au.'
<class 'str'> 79 {"name": "Tom", "age": 20, "interest": ["music", "movie"], "class": ["Python"]}
<class 'bytes'> 51 b'\x84\xa4name\xa3Tom\xa3age\x14\xa8interest\x92\xa5music\xa5movie\
xa5class\x91\xa6Python'
  在这个示例中,之所以pickle库比json库序列化的结果长,主要是因为pickle库要解决所有Python类型数据的序列化,记录各种数据类型,包括自定义的类。而json库只需要支持少数几种类型,都不需要类型的描述字符,所以很简单。但大多数情况下,我们序列化的数据都是这些简单的类型,因此采用JSON即可。msgpack库的序列化结果占用空间最小,压缩效率最高。
  区别选择
  json库的优点是跨语言、跨平台,应用范围大,体积小;缺点是只能支持int、str、list、tuple、dict等基本的Python数据结构。pickle库的优点是专为Python设计,支持Python的几乎所有数据类型;缺点是只能在Python中使用,存储数据占用的空间大。而msgpack库简单易用,高效压缩,支持语言丰富。Python很多知名的库都使用msgpack库。
  4.13  本章小结
  通过学习本章,希望大家学会日常使用频繁的Python操作,我们一方面要适时借助他人封装好的库提升开发效率,另一方面要结合自己需求,实现个性化封装,以便后续在其他项目中复用。
版权声明:51Testing软件测试网获得作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号