在Python 3中加载Python 2的.npy文件

14 投票
3 回答
9498 浏览
提问于 2025-04-18 09:01

我正在尝试加载 /usr/share/matplotlib/sample_data/goog.npy 这个文件:

datafile = matplotlib.cbook.get_sample_data('goog.npy', asfileobj=False)
np.load(datafile)

在 Python 2.7 中可以正常工作,但在 Python 3.4 中却出现了错误:

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

我猜这可能和 Python 2 和 Python 3 之间的 bytes/str/unicode 不一致有关,但我不知道该怎么解决。

问题是:

  • 如何在 Python 3 中加载一个来自 Python 2 的 .npy 文件(NumPy 数据)?

3 个回答

2

我找到的一个解决办法是,把在python2.*中加载的numpy数组保存到一个csv文件里,然后再在python3.*中读取这个文件。

# Dump in python2
import numpy as np

datafile = matplotlib.cbook.get_sample_data('goog.npy', asfileobj=False)
arr = np.load(datafile)
np.savetxt("np_arr.csv", arr, delimiter=",")

现在在python3中读取这个文件。

# Load in python3
import numpy as np
arr = np.loadtxt(open("np_arr.csv"), delimiter=",")
6

在使用Python 3.5和numpy 1.10.4的时候,使用下面这个命令对我来说是有效的;

D = np.load(file, encoding = 'latin1')

如果我不指定编码的话,就会出现相同的错误信息。

7

问题在于这个文件里包含了被序列化(也就是“腌制”过的)Python日期时间对象,而不仅仅是数字数据。Python对这些对象的序列化格式在Python 2和Python 3之间是不兼容的。

python2
>>> import pickle
>>> pickle.dumps(datetime.datetime.now())
"cdatetime\ndatetime\np0\n(S'\\x07\\xde\\x06\\t\\x0c\\r\\x19\\x0f\\x1fP'\np1\ntp2\nRp3\n."

还有

python3
>>> import pickle
>>> pickle.loads(b"cdatetime\ndatetime\np0\n(S'\\x07\\xde\\x06\\t\\x0c\\r\\x19\\x0f\x1fP'\np1\ntp2\nRp3\n.")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xde in position 1: ordinal not in range(128)

一个解决办法是在Numpy代码中进行修改

numpy/lib/format.py:
...
446         array = pickle.load(fp)

变成 array = pickle.load(fp, encoding="bytes")。更好的解决方案是让 numpy.load 能够传递编码参数。

撰写回答