Python对象序列化与反序列化完全指南 - 从入门到精通
- Python
- 2025-08-01
- 968
Python对象序列化与反序列化完全指南
最后更新日期:2023年10月15日
本教程将详细讲解Python中对象序列化与反序列化的概念、常用模块(pickle, json, yaml)的使用方法、性能对比以及安全性注意事项。
目录
1. 什么是序列化与反序列化?
序列化是将Python对象转换为可存储或传输的格式(如字节流、字符串)的过程。反序列化则是将序列化后的数据恢复为Python对象的过程。
主要应用场景:
- 数据持久化:将对象保存到文件或数据库中
- 网络传输:在客户端和服务器之间传输对象
- 进程间通信:在不同进程间传递对象
- 缓存:将对象缓存到内存或磁盘
序列化过程
Python对象 → 序列化模块 → 字节流/字符串
反序列化过程
字节流/字符串 → 反序列化模块 → Python对象
2. Python pickle模块
pickle是Python特有的序列化模块,可以处理几乎所有的Python对象,包括自定义类实例。
基本用法示例:
import pickle
# 定义一个示例类
class User:
def __init__(self, name, email, age):
self.name = name
self.email = email
self.age = age
def __repr__(self):
return f"User(name='{self.name}', email='{self.email}', age={self.age})"
# 创建对象
user = User("张三", "zhangsan@example.com", 28)
# 序列化到文件
with open("user.pickle", "wb") as f:
pickle.dump(user, f)
# 从文件反序列化
with open("user.pickle", "rb") as f:
loaded_user = pickle.load(f)
print(loaded_user) # 输出: User(name='张三', email='zhangsan@example.com', age=28)
pickle模块特点:
- 支持几乎所有Python数据类型
- 生成的是二进制格式,不可读
- 只能用于Python环境
- 存在安全风险(可能执行任意代码)
- 支持协议版本(默认为最高版本)
3. Python json模块
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,json模块提供了JSON编码和解码功能。
基本用法示例:
import json
# Python对象
data = {
"name": "张三",
"age": 28,
"married": False,
"hobbies": ["阅读", "游泳", "编程"],
"address": {
"city": "北京",
"street": "中关村大街"
}
}
# 序列化到文件
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
# 从文件反序列化
with open("data.json", "r", encoding="utf-8") as f:
loaded_data = json.load(f)
print(loaded_data["name"]) # 输出: 张三
处理自定义对象:
class User:
def __init__(self, name, email, age):
self.name = name
self.email = email
self.age = age
# 自定义编码器
class UserEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, User):
return {"name": obj.name, "email": obj.email, "age": obj.age}
return super().default(obj)
# 自定义解码器
def user_decoder(dct):
if "name" in dct and "email" in dct and "age" in dct:
return User(dct["name"], dct["email"], dct["age"])
return dct
user = User("李四", "lisi@example.com", 32)
# 序列化
user_json = json.dumps(user, cls=UserEncoder, indent=2)
print(user_json)
# 反序列化
loaded_user = json.loads(user_json, object_hook=user_decoder)
print(loaded_user.name) # 输出: 李四
4. Python yaml模块
YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化格式,常用于配置文件。
基本用法示例:
# 需要先安装PyYAML: pip install pyyaml
import yaml
# Python对象
config = {
"database": {
"host": "localhost",
"port": 5432,
"username": "admin",
"password": "secret"
},
"logging": {
"level": "DEBUG",
"file": "/var/log/app.log"
}
}
# 序列化到文件
with open("config.yaml", "w") as f:
yaml.dump(config, f, sort_keys=False)
# 从文件反序列化
with open("config.yaml", "r") as f:
loaded_config = yaml.safe_load(f)
print(loaded_config["database"]["host"]) # 输出: localhost
YAML特点:
- 人类可读性高
- 支持复杂数据结构
- 支持注释
- 多语言支持
- 使用
safe_load避免安全风险
5. 三种序列化方式对比
| 特性 | pickle | json | yaml |
|---|---|---|---|
| 可读性 | 二进制,不可读 | 良好 | 优秀 |
| 支持数据类型 | 所有Python对象 | 基本类型+dict/list | 丰富(包括时间等) |
| 跨语言支持 | 仅Python | 几乎所有语言 | 良好 |
| 安全性 | 低(可执行任意代码) | 高 | 中(需使用safe_load) |
| 性能 | 高 | 高 | 中低 |
| 典型应用 | Python内部数据存储 | Web API,数据交换 | 配置文件,数据持久化 |
选择建议:
- 仅在Python环境内使用 → pickle
- 需要跨语言支持 → json
- 需要人类可读性 → yaml
- 处理配置文件 → yaml
- 高性能需求 → pickle或json
6. 安全性注意事项
pickle安全风险:
pickle模块在反序列化时会自动执行对象的__reduce__方法,这可能导致任意代码执行:
import pickle # 恶意pickle数据 malicious_data = b"\x80\x04\x95.\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94\x8c\x0ctouch /tmp/hacked\x94\x85\x94R\x94." # 反序列化会执行系统命令 pickle.loads(malicious_data) # 会在/tmp目录创建hacked文件
安全建议:
- 不要反序列化来自不受信任来源的pickle数据
- 考虑使用更安全的序列化格式(如json)
- 如果必须使用,可以考虑使用
pickletools分析数据
其他安全建议:
- 使用json时:避免使用
json.loads解析不受信任的数据(可能造成拒绝服务攻击) - 使用yaml时:始终使用
yaml.safe_load而不是yaml.load - 验证和清理所有输入数据
- 使用数字签名验证数据来源
- 在沙箱环境中处理不受信任的数据
7. 最佳实践总结
通用实践
- 优先使用JSON进行跨语言数据交换
- 使用YAML处理配置文件
- 仅在信任的环境中使用pickle
- 始终处理序列化/反序列化异常
性能优化
- 大型数据集使用二进制格式
- 考虑使用更高效的库如
ujson或orjson - 避免不必要的数据序列化
- 使用协议缓冲区处理高性能场景
进阶技巧
- 使用
__getstate__和__setstate__控制pickle行为 - 利用
json.JSONEncoder自定义复杂对象序列化 - 使用YAML锚点和别名减少重复
- 考虑使用Schema验证反序列化数据
最终建议:
选择序列化方法时,应综合考虑以下因素:数据敏感度、使用环境、性能需求、跨语言需求、可读性要求。在大多数情况下,JSON是最佳选择,它提供了良好的平衡点。
对于纯Python环境且需要处理复杂对象,pickle是高效的解决方案。对于配置文件和需要人工编辑的场景,YAML是最合适的。
希望本教程能帮助您掌握Python中的序列化与反序列化技术!如有任何问题或建议,欢迎留言讨论。
本文由GuanGong于2025-08-01发表在吾爱品聚,如有疑问,请联系我们。
本文链接:http://pjw.521pj.cn/20257047.html
发表评论