在数据持久化、网络传输和跨平台数据交换等应用场景,经常会使用到序列化和反序列化技术。本文小编与大家分享 Python 序列化和反序列化的相关知识。
一、什么是序列化和反序列化
(一)序列化和反序列化的概率
序列化和反序列化是互为逆过程的关系,就像打包和拆包一样。
【小编提示】 序列化与持久化不是一个概念,其核心差异在于:序列化解决“数据格式转换与传输”问题(例如,将内存中的对象状态转换为字节流,以便存储或传输),持久化解决“数据长期存储与生存期”问题(例如,将内存数据保存到硬盘文件,防止断电丢失)。序列化是持久化的常见前置手段,但二者并非等同。 序列化(对象→流)和反序列化(流→对象)是技术实现手段,持久化(瞬时态→持久态)是业务目标状态。若需将对象永久保存,通常流程为:对象 → 序列化 → 写入外存(持久化) 。 |
二、Python 序列化和反序列化
Python 中有多个标准库可以实现序列化和反序列化功能,下面对常用标准库模块进行简单介绍。
(一)json 模块
json 模块是 Python 标准库组成,其json.dumps()、json.dump() 函数可用于序列化,而 json.loads()、json.load() 函数可用于反序列化。由于前文已介绍过 json 模块,下面直接使用代码示例:
1、将字典序列化为 JSON 文件
import jsondata = {'name': 'Jack', 'age': 20}# 将字典转换为JSON 格式字符串json_str = json.dumps(data)print(json_str)# 将 JSON 格式字符串序列化到 JSON 文件with open("json_data.json", "w") as f: f.write(json_str)print("字典已序列化到 JSON 文件")
程序输出:
>>> %Run jsontofile.py{"name": "Jack", "age": 20}字典已序列化到 JSON 文件>>>
2、将 JSON 文件反序列化为字典
import json# 将 JSON 文件读取到字典对象with open("json_data.json", "r") as f: json_data = json.load(f)print(type(json_data))print(json_data)
程序输出:
>>> %Run filetojson.py<class 'dict'>{'name': 'Jack', 'age': 20}>>>
【小编提示】 json 模块默认只支持基本数据类型(dict、list、str、int、float、bool、None)的序列化和反序列化,自定义对象需要自行定义方法进行转换。 |
(二)xml.etree.ElementTree 模块( ET 模块)
ET 模块是 Python 标准库组成,ET模块的fromstring() 函数、ElementTree 对象的 write() 方法等可用于序列化,ET 模块的 parse() 函数可用于反序列化。前文已介绍过 ET 模块,此处代码示例省略。
(三)pickle 模块
pickle 模块是 Python 标准库组成,用于将 Python 对象序列化为字节流,以便可以将这些对象保存到文件中或者通过网络传输。pickle 模块可以处理几乎所有的 Python 对象类型。
在序列化过程中,pickle 模块会递归地遍历对象的所有成员,并将其转化为字节流。在反序列化过程中,pickle 模块会根据字节流的结构重新构建出原始对象。
1、序列化对象
可以使用 pickle.dumps() 函数序列化对象,它会返回对象的序列化后的字节表示。
import pickle# 创建一个 Python 字典对象dict_data = {'a': 1, 'b': 2, 'c': 3}# 序列化对象bytes_data = pickle.dumps(dict_data) # 输出序列化后的字节流print(bytes_data)
程序输出:
>>> %Run pickle_1.pyb'\x80\x04\x95\x17\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x01a\x94K\x01\x8c\x01b\x94K\x02\x8c\x01c\x94K\x03u.'>>>
2、存储对象到文件
使用 pickle.dump() 函数序列化对象存储到文件。
import pickle# 创建一个Python 字典对象data = {'a': 1, 'b': 2, 'c': 3}# 将对象存储到文件with open('bytes_data.pkl', 'wb') as f: pickle.dump(data, f)print("字典对象已序列化到文件")
程序输出:
>>> %Run pickle_2.py字典对象已序列化到文件>>>
3、反序列化对象
可以使用 pickle.loads()函数(从字节流中读取)或 pickle.load() 函数(从文件中读取)。
import pickle# 从字节流中反序列化对象bytes_data = b'\x80\x04\x95\x17\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x01a\x94K\x01\x8c\x01b\x94K\x02\x8c\x01c\x94K\x03u.'data = pickle.loads(bytes_data)print("从字节流中反序列化对象:", data) # 从文件中反序列化对象with open('bytes_data.pkl', 'rb') as f: file_data = pickle.load(f)print("从文件中反序列化对象:", file_data)
程序输出:
>>> %Run pickle_3.py从字节流中反序列化对象: {'a': 1, 'b': 2, 'c': 3}从文件中反序列化对象: {'a': 1, 'b': 2, 'c': 3}>>>
【小编提示】 使用 pickle 模块进行反序列化时需要特别注意安全性问题,因为不安全的对象可以被反序列化并执行恶意代码。只从可信来源反序列化数据,或者使用 safe_load() 函数来减少风险。 |
除以上介绍的标准库模块之外,还有很多其他模块和第三方库,大家可以根据需要查阅官方文档和网络教程学习和使用。