为什么Python 3 Pickle无法读取Python 2 Pickle数据?

发布于 2025-02-07 12:51:26 字数 768 浏览 2 评论 0原文

我有一个Python 2泡菜文件,当我尝试使用Python 3读取它时,它显示以下错误:

UnicodeDecodeError:'ascii'编解码器无法解码BYTE 0xc3位置0:不在范围(128)< /code>

以下是Python 2和Python 3中的一些代码样本:

python_2_dump.py

# -*- coding: utf-8 -*-
# Python 2 version
import cPickle

test = {
  'Á': 'A',
  'á': 'a',
  'Ã': 'A',
  'ã': 'a',
  'Â': 'A',
  'â': 'a',
}

with open('test.pickle', 'w') as f:
  cPickle.dump(test, f)

python_3_3_load.py

# Python 3 version
import pickle

with open('test.pickle', 'rb') as f:
  print(pickle.load(f))

是否有任何原因Python 3未检测到旧协议并转换转换相应吗?如果相反,即Python 2阅读Python 3腌制数据,那是有道理的。

I have a Python 2 pickle file that when I try to read it with Python 3 it shows the following error:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Here are some code sample in Python 2 and Python 3:

python_2_dump.py

# -*- coding: utf-8 -*-
# Python 2 version
import cPickle

test = {
  'Á': 'A',
  'á': 'a',
  'Ã': 'A',
  'ã': 'a',
  'Â': 'A',
  'â': 'a',
}

with open('test.pickle', 'w') as f:
  cPickle.dump(test, f)

python_3_load.py

# Python 3 version
import pickle

with open('test.pickle', 'rb') as f:
  print(pickle.load(f))

Is there any reason Python 3 doesn't detect the old protocol and convert it accordingly? If it was the other way around, i.e. Python 2 reading a Python 3 pickle data, it makes sense.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

香草可樂 2025-02-14 12:51:28

自动检测到泡菜的协议版本,因此没有
需要协议参数。

但是,您需要使用fix_imports编码errors来控制Python 2生成的Pickle流的兼容性支持。 https://docs.python.org/3.10/library/pickle.html#pickle.unpickler“ rel =“ nofollow noreferrer”>相关文档:

可选参数fix_imports编码errors用于
Python 2生成的泡菜流的控制兼容性支持。
如果fix_imports是正确的,那么Pickle将尝试映射旧的Python 2个名称
python 3中使用的新名称。编码错误
如何解码python 2腌制的8位字符串实例;这些
默认为“ ASCII”和“严格”。编码可以是
“字节”将这些8位字符串实例读取为字节对象。使用
numpy阵列需要编码='latin1'和
DateTime的实例,日期和时间由Python2。


在您的示例中,它将读取test.pickle,如果您通过encoding ='utf-8'

<代码> print(pickle.load(f,encoding ='utf-8'))

输出:

{'Ã': 'A', 'â': 'a', 'Á': 'A', 'ã': 'a', 'Â': 'A', 'á': 'a'}

The protocol is detected automatically, as stated in the docs:

The protocol version of the pickle is detected automatically, so no
protocol argument is needed.

However, you need to use fix_imports, encoding and errors to control compatibility support for pickle stream generated by Python 2. The relevant docs:

The optional arguments fix_imports, encoding and errors are used to
control compatibility support for pickle stream generated by Python 2.
If fix_imports is true, pickle will try to map the old Python 2 names
to the new names used in Python 3. The encoding and errors tell pickle
how to decode 8-bit string instances pickled by Python 2; these
default to ‘ASCII’ and ‘strict’, respectively. The encoding can be
‘bytes’ to read these 8-bit string instances as bytes objects. Using
encoding='latin1' is required for unpickling NumPy arrays and
instances of datetime, date and time pickled by Python 2.

In your example, it will read the test.pickle if you pass encoding='utf-8':

print(pickle.load(f, encoding='utf-8'))

output:

{'Ã': 'A', 'â': 'a', 'Á': 'A', 'ã': 'a', 'Â': 'A', 'á': 'a'}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文