Python 标准库中 pickle 模块的基本用法
pickle 是 Python 标准库里用来做对象序列化和反序列化的模块。➡️
- 序列化:把 Python 对象变成字节流,方便保存到文件
- 反序列化:把字节流再恢复成原来的 Python 对象
Python中有
- 列表、字典、元组、集合
- 自定义类对象
- 训练好的模型对象
- 中间计算结果 等各种对象,怎么存取这些对象?
这个时候就可以用到
pickle模块。
pickle可以把 Python 里的对象“打包存盘”,以后再“原样读回来”。
1. 基本用法
1.1 保存对象到文件
1 | |
说明:
"wb"表示以二进制写入pickle.dump(obj, file)表示把对象写入文件
1.2 从文件读取对象
1 | |
说明:
"rb"表示以二进制读取pickle.load(file)表示从文件中恢复对象
不写文件,直接转成字节
1.3 对象转字节
1 | |
这里:
dumps()返回的是字节对象- 末尾有个
s,可以理解为“dump to string/bytes”
1.4 从字节恢复对象
1 | |
这里:
loads()从字节中恢复对象
2. 四个最常用函数
pickle 里最常见的就是这四个:
pickle.dump(obj, file)把对象写到文件pickle.load(file)从文件读回对象pickle.dumps(obj)把对象转成字节pickle.loads(bytes_obj)从字节恢复对象
3. 一个完整的小例子
1 | |
4. 常见应用场景
4.1 保存机器学习模型或中间结果
例如:
1 | |
4.2 缓存计算结果
某些计算很耗时,可以先保存,下次直接读取。
5. 注意事项
5.1 pickle 文件不是通用格式
它主要给 Python 用,不适合和其他语言交换数据。 如果你想和别的语言或系统交互,通常更适合用:
- JSON
- CSV
- YAML
- Parquet
5.2 不能随便加载不可信的 .pkl 文件
这是最重要的一点。
pickle.load() 在反序列化时,可能执行恶意代码。 所以:
- 只加载你自己生成的
.pkl文件 - 不要随便打开网上下载的
.pkl文件
5.3 保存自定义类对象时,pickle 依赖类的模块路径
特别是保存了自定义类对象时,后面改了类定义、模块名或文件结构,旧的 pickle 文件可能不能正常恢复。
这是因为 pickle 保存对象时,通常不会把这个类的方法代码一起完整打包进去,而是主要保存:
- 对象所属的模块名和类名
- 对象的属性数据(状态)
比如一个对象原来属于 utils.SimpleProblem,那么在反序列化时,pickle.load() 会尝试:
- 重新导入
utils - 找到其中的
SimpleProblem - 再把之前保存的属性恢复到对象里
如果此时:
utils.py被删了SimpleProblem被移动到别的文件了- 类名改了
- 类结构变了
那么就可能出现类似错误:
1 | |
所以要注意:
- 如果 pickle 里保存的是自定义类对象,后续不要随意改模块路径和类名
- 如果代码结构已经调整,旧 pickle 文件可能也要重新生成
- 更稳妥的做法是只保存纯数据(如字典、列表、张量),再手动重建对象
6. 和 JSON 的区别
6.1 pickle
优点:
- 能保存更多 Python 对象类型
- 使用方便
- 适合 Python 内部使用
缺点:
- 不安全
- 不通用
- 可读性差
6.2 json
优点:
- 通用
- 文本格式,可读性好
- 更安全
缺点:
- 只能保存基本数据类型
- 不能直接保存很多复杂 Python 对象
7. 什么时候用 pickle
适合:
- Python 项目内部临时存数据
- 保存训练中间结果
- 保存复杂对象结构
不适合:
- 跨语言数据交换
- 存长期重要数据
- 处理不可信来源文件
Python 标准库中 pickle 模块的基本用法
https://nanana-szz.github.io/04-pickle/