Python2生成的pickle文件在Python3加载失败,求解决方案
解决Python3加载Python2创建的Pickle文件问题
别担心,先别急着判定文件损坏——这种情况大概率是Python2和Python3的Pickle兼容性问题,尤其是字符串编码的差异导致的,咱们一步步来解决:
先复盘你遇到的问题
你尝试的几种打开方式都踩了跨版本Pickle的坑:
- 用Python2风格的
'r'模式打开:Python3中文本模式默认用ascii编码解析,遇到文件里的utf-8字节直接编码报错 - 加
encoding='utf-8'的文本模式打开:Pickle需要二进制流才能解析,文本模式返回的是str对象,类型完全不匹配 - 二进制模式加encoding参数:二进制模式本身不需要编码参数,直接触发参数错误
- 纯二进制模式打开:因为Python2和Python3的字符串存储逻辑差异,导致Pickle解析时识别到无效的加载标记
可行的解决方案
按顺序试试下面这几种方法:
方法1:指定encoding为'latin1'(最常用的解决方法)
Python2中的str对象在Pickle里是以字节流形式存储的,Python3加载时用latin1编码可以无损转换这些字节,不会丢失任何信息:
import _pickle as pickle with open('filename', 'rb') as f: foo, bar = pickle.load(f, encoding='latin1')
方法2:指定encoding为'utf-8'并忽略错误
如果你的文件里确实包含utf-8编码的字符串,可以指定utf-8编码,同时用errors='replace'忽略个别无法解析的字符(谨慎使用,可能丢失少量非关键信息):
import _pickle as pickle with open('filename', 'rb') as f: foo, bar = pickle.load(f, encoding='utf-8', errors='replace')
方法3:手动读取字节后加载
如果上面的方法都不行,先把文件完整读成字节数据,再用pickle.loads加载并指定编码:
import _pickle as pickle with open('filename', 'rb') as f: pickle_data = f.read() foo, bar = pickle.loads(pickle_data, encoding='latin1')
为什么这些方法有效?
Python2和Python3的字符串模型差异很大:Python2的str是字节序列,unicode才是真正的字符串;而Python3的str是Unicode字符串,bytes是字节序列。Pickle跨版本保存/加载时,默认的编码处理逻辑不兼容,指定encoding参数就是告诉Python3如何把Python2的字节流转换成正确的字符串对象。
如果以上方法全部失败,那才需要考虑文件是否损坏——但从你报错的UnpicklingError: invalid load key, ' '来看,更可能是编码不匹配,而非文件本身损坏。
内容的提问来源于stack exchange,提问作者Novak
相关产品推荐
相关产品推荐

