用Python3取消勾选Python2对象

用Python3取消勾选Python2对象,python,python-3.x,pickle,python-2.4,python-2to3,Python,Python 3.x,Pickle,Python 2.4,Python 2to3,我想知道是否有办法加载在Python2.4和Python3.4中经过pickle处理的对象 我一直在大量公司遗留代码上运行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'))

我想知道是否有办法加载在Python2.4和Python3.4中经过pickle处理的对象

我一直在大量公司遗留代码上运行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)
查看争用中的pickle对象,它是
dict
中的
dict
,包含
str
类型的键和值


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

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

默认情况下,尝试将所有字符串数据解码为ASCII,但解码失败。见:

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

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

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 
但是您需要验证您的字符串是否使用了错误的编解码器解码;Latin-1适用于任何输入,因为它将字节值0-255直接映射到前256个Unicode码点

另一种方法是加载带有
encoding='bytes'
的数据,然后解码所有
字节
键和值


请注意,在3.6.8、3.7.2和3.8.0之前的Python版本中,除非使用
encoding='bytes'
,否则使用
encoding='latin1'
会在对象中包含numpy数组时导致一些问题

使用
encoding='bytes'
会更好


有关使用
encoding='bytes'

的完整说明,请参见此部分。Python 2.4是否具有
json
模块?也许您可以编写一个2.4脚本来取消对对象的pickle并将其保存为json对象,然后编写一个3.4脚本来读取json对象并将其保存为与3.4兼容的pickle对象。这将是对所有pickle文件运行的一次性操作。我也在考虑类似的问题,考虑到这些是dict,我想我可以将sys.stdout更改为一个文件并打印出来,但我想看看是否可以先加载它们,这是一个与日期时间有关的问题:如何使其与Python 2向后兼容?显然,Python2不存在编码参数。@EpicAdv:您不需要使此代码与Python2兼容;这个问题是关于如何将Python2 pickle加载到Python3中。对于Python2,完全删除
encoding
关键字。@EpicAdv:您可以创建一个pickle\u选项字典,该字典对于Python2是空的,或者具有
“encoding”:“latin1”
并将**pickle\u选项发送到pickle。这样,它应该在两个版本中都运行。@pipefish-聪明,但在某些地方,您必须检测您正在使用的版本,因此您也可以更直接地根据版本的不同(一个带额外参数,一个不带额外参数)执行不同的调用。但至少你得到了EpicAdv评论的要点,Martijn的评论根本没有提到。我意识到
datetime
评论不是这个答案的主旨,但对于未来的读者,我想指出,即使是“固定的”Python3的版本仍然需要
encoding='latin-1'
来取消勾选Python2日期时间。如果您的pickle Python 2数据碰巧同时包含datetimes和ByTestRing,而不是用拉丁语1编码,那么您可能还是最好还是使用
encoding='bytes'
。哪些问题?我应该注意什么?使用
bytes
将字符串转换成bytes(),因此如果可能,我更喜欢
latin1
,但我不清楚问题出在哪里。@sreeragh-a-r:您能举一个您遇到的问题的例子吗?我有一个二维的
numpy.ndarray
(numpy 1.14)在Python2.7中使用
cPickle.dumps()
,在Python3中使用
pickle.loads(…,encoding='latin1')
进行了pickle处理。@djvg我在不得不将图像作为图像字符串进行pickle处理并取消pickle处理时遇到了一些问题。代码可以在这里找到@Gulzar请参见上述问题要点。取消勾选后图像已损坏。如果您不使用
np.array
可以省去一些麻烦,并保留
encoding='latin1'
,这样您就不必将所有
字节解码为
str