用 python3解压 python2对象

我想知道是否有一种方法可以加载在 Python 2.4中使用 Python 3.4进行 pickle 的对象。

我已经在大量的公司遗留代码上运行了2到3次,以使其更新。

这样做之后,在运行该文件时,我得到以下错误:

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

查看争用的 pickle 对象,它是 dict中的 dict,包含类型为 str的键和值。

所以我的问题是: 有没有一种方法可以用 python 3.4加载最初在 python 2.4中腌制的对象?

99148 次浏览

您必须告诉 pickle.load()如何将 Python bytestring 数据转换为 Python3字符串,或者告诉 pickle将它们保留为字节。

默认设置是尝试将所有字符串数据解码为 ASCII,解码失败:

可选的关键字参数是 Fix _ import 修复 _ 导入编码错误,它们用于控制对 Python 2生成的 pickle 流的兼容性支持。如果 Fix _ import 修复 _ 导入为 true,pickle 将尝试将旧的 Python2名称映射到 Python3中使用的新名称。编码错误告诉 pickle 如何解码 Python 2 pickle 的8位字符串实例; 这些实例分别默认为“ ASCII”和“ strong”。编码可以是“字节”,以字节对象的形式读取这些8位字符串实例。

将编码设置为 latin1允许您直接导入数据:

with open(mshelffile, 'rb') as f:
d = pickle.load(f, encoding='latin1')

但是您需要验证没有一个字符串是用错误的编解码器解码的; 对于任何输入,拉丁 -1都可以工作,因为它直接将字节值0-255映射到前256个 Unicode 编码点。

另一种方法是使用 encoding='bytes'加载数据,然后对所有 bytes键和值进行解码。

请注意,除非使用 encoding='bytes',否则在3.6.8、3.7.2和3.8.0,对 Python2datetime对象数据的解压缩被破坏之前的 Python 版本都是如此。

当对象中包含 numpy 数组时,使用 encoding='latin1'会导致一些问题。

使用 encoding='bytes'会更好。

有关使用 encoding='bytes'的完整说明,请参阅此 回答