使用 gzip 和 pickle 时出现 UnicodeDecodeError

Posted

技术标签:

【中文标题】使用 gzip 和 pickle 时出现 UnicodeDecodeError【英文标题】:UnicodeDecodeError while using gzip and pickle 【发布时间】:2017-12-04 07:26:09 【问题描述】:

我正在使用 mnist 数据的练习代码在 Python 3.4

中进行深度学习

原代码是

import _pickle as cPickle
def load_data():
    f = gzip.open('../data/mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = cPickle.load(f)
    f.close()
    return (training_data, validation_data, test_data)
def load_data_wrapper():
    tr_d, va_d, te_d = load_data()
    ....

但是导致UnicodeDecodeError,根据网上的建议,我把cPickle.load(f)改成pickle.load(f, encoding='latin1')

当我在shell中运行时也会出现同样的错误

>>> training_data, validation_data, test_data = \
... mnist_loader.load_data_wrapper() \
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "C:\E\Deep Learning Tutorial\neural-networks-and-deep-learning-master\src\mnist_loader.py", line 68, in load_data_wrapper
tr_d, va_d, te_d = load_data()
  File "C:\E\Deep Learning Tutorial\neural-networks-and-deep-learning-master\src\mnist_loader.py", line 43, in load_data

并且错误行追溯到:

f = gzip.open('../data/mnist.pkl.gz', 'rb')

和以前一样的错误,但只发生在不同的行

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

如何解决这个问题?

【问题讨论】:

您是否尝试将 `# -- coding: utf-8 --` 行放在文件的最顶部 @csharpcoder 我试过你的代码。添加后,错误是一样的,但是错误行变成了f.close(),真是奇怪 @csharpcoder 另外,如果我把注释行#training_data, validation_data, test_data = cPickle.load(f),那么错误行将变为#training_data, validation_data, test_data = cPickle.load(f) 尝试使用pickle.load(f, encoding='bytes')。它告诉 pickle 如何解码由 Python 2 腌制的 8 位字符串实例,默认为 ‘ASCII’ @martineau 链接是github.com/mnielsen/neural-networks-and-deep-learning/archive/…,非常感谢您的好意! 【参考方案1】:

首先,我能够使用从我下载的https://github.com/mnielsen/neural-networks-and-deep-learning/archive/master.zip 存档中提取的mnist.pkl.gz 数据文件来重现该问题。 pickle.load(f) 调用引发以下异常:

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

但是,当我按照我在您问题下的评论中的建议将 encoding='bytes' 参数添加到 pickle.load() 调用时,错误消失了。

另一个变化是将import _pickle as cPickle 替换为import pickle,但我认为这并不重要(请参阅What difference between pickle and _pickle in python 3?)。

可能的其他显着差异是我在 Windows 上使用 Python 3.6.3。

import gzip
import pickle

def load_data():
    f = gzip.open('mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = \
        pickle.load(f, encoding='bytes')  # Note encoding argument value.
    f.close()
    return (training_data, validation_data, test_data)

def load_data_wrapper():
    tr_d, va_d, te_d = load_data()
    print('gzipped pickled data loaded successfully')

load_data_wrapper()

题外话: load_data() 函数可以写得更简洁一些:

def load_data():
    with gzip.open('mnist.pkl.gz', 'rb') as f:
        training_data, validation_data, test_data = \
            pickle.load(f, encoding='bytes')
    return training_data, validation_data, test_data

【讨论】:

我想我明白了第一次尝试失败的原因。每次更改代码时,我都必须终止 python shell 并重新运行,否则更改的代码将不起作用。以前,我没有终止 shell。并且您的评论是正确答案,谢谢! 添加 encoding='bytes' 作为 load(..) 的第二个参数为我在 Python 3.7 中解决了 UnicodeDecodeError

以上是关于使用 gzip 和 pickle 时出现 UnicodeDecodeError的主要内容,如果未能解决你的问题,请参考以下文章

尝试从 BigQuery 读取表并使用 Airflow 将其保存为数据框时出现 _pickle.PicklingError

运行我的应用程序时出现 Angular2 GZIP 问题

关于VS2015 字符集采用Unicode时出现的问题

python pickle 上的命名空间

当我尝试使用朴素贝叶斯/Python进行预测时出现尺寸不匹配错误

Python 3 - pickle 可以处理大于 4GB 的字节对象吗?