Skip to content

处理Python 3.7中的"Unsupported Pickle Protocol 5"错误

问题描述

当在 Python 3.7 环境中尝试使用 pickle.load() 加载使用 Protocol 5 序列化的 pickle 文件时,会遇到以下错误:

python
config = pickle.load(open(f"{path}/params.pkl", "rb"))
ValueError: unsupported pickle protocol: 5

这是因为 Python 3.7 最高只支持到 Protocol 4,而 Protocol 5 是在 Python 3.8 中引入的。当文件是在 Python 3.8+ 版本序列化后,在低版本 Python 中加载就会出现此问题。

解决方案

方法一:安装并使用 pickle5 库(推荐)

这是最直接的解决方案,特别适合无法升级Python版本的情况:

bash
pip install pickle5

然后在代码中使用:

python
import pickle5 as pickle

with open("path/to/protocol5.pkl", "rb") as f:
    data = pickle.load(f)

TIP

这种方法特别适合在 Google Colab(默认使用 Python 3.7)、Heroku 或其他受限制的环境中处理 Protocol 5 pickle 文件。

方法二:转换 pickle 协议版本

如果有权访问 Python 3.8+ 环境,可以将文件重新序列化为 Protocol 4:

python
# 在 Python 3.8+ 环境中执行
with open("protocol5_file.pkl", "rb") as f:
    data = pickle.load(f)

# 保存为 Protocol 4
with open("protocol4_file.pkl", "wb") as f:
    pickle.dump(data, f, protocol=4)

然后就可以在 Python 3.7 中正常加载了。

方法三:确保环境一致性

如果是在部署环境中遇到此问题(如Heroku),检查并确保开发和部署环境的Python版本一致:

  1. 创建 runtime.txt 文件
  2. 指定与本地环境相同的Python版本:
python-3.9.2

方法四:特定框架解决方案

对于稳定基线3(stable-baselines3)用户:

bash
pip install --upgrade cloudpickle pickle5
python
from stable_baselines3 import PPO

custom_objects = {
    "lr_schedule": lambda x: .003,
    "clip_range": lambda x: .02
}
model = PPO.load("path/to/model.zip", custom_objects=custom_objects)

协议版本兼容性表

Python版本最高支持的Pickle协议
Python 3.4Protocol 4
Python 3.5-3.7Protocol 4
Python 3.8+Protocol 5

最佳实践建议

  1. 明确指定协议版本:在序列化时指定兼容的协议版本

    python
    pickle.dump(data, file, protocol=4)  # 确保向后兼容
  2. 文档记录:在项目中记录使用的 pickle 协议版本

  3. 环境管理:使用虚拟环境或容器化技术确保环境一致性

注意

不同协议版本在性能和功能上有所差异。Protocol 5 支持内存映射和更高效的大型对象处理,但牺牲了向后兼容性。

总结

"Unsupported Pickle Protocol 5" 错误通常是由于Python版本不匹配导致的。通过安装 pickle5 库、转换协议版本或确保环境一致性,可以有效解决此问题。在生产环境中,建议明确指定兼容的协议版本并保持环境的一致性。