143

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

我一直在对大量公司遗留代码运行 2to3 以使其保持最新状态。

完成此操作后,在运行文件时出现以下错误:

  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)

查看竞争中的腌制对象,它是 a dictin a dict,包含 type 的键和值str

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

4

2 回答 2

204

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

默认设置是尝试将所有字符串数据解码为 ASCII,但解码失败。请参阅pickle.load()文档

可选的关键字参数是fix_importsencodingerrors,它们用于控制对 Python 2 生成的 pickle 流的兼容性支持。如果fix_imports为 true,pickle 将尝试将旧的 Python 2 名称映射到 Python 3 中使用的新名称。encodingerrors告诉 pickle 如何解码 Python 2 腌制的 8 位字符串实例;这些默认分别为“ASCII”和“严格”。编码可以是“字节”,以将这些 8 位字符串实例读取为字节对象。

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

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

但是您需要验证您的所有字符串都没有使用错误的编解码器进行解码;Latin-1 适用于任何输入,因为它将字节值 0-255 直接映射到前 256 个 Unicode 代码点。

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

请注意,直到 3.6.8、3.7.2 和 3.8.0 之前的 Python 版本,除非datetime使用encoding='bytes'.

于 2015-01-29T15:38:01.850 回答
19

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

使用encoding='bytes'会更好。

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

于 2017-12-19T08:39:21.213 回答