pickle模块实现了把Python对象结构进行序列化和反序列化( serializing and de-serializing a Python object structure)的二进制协议。
pickling: 把对象序列化为字节流a byte stream
unpickling: 把二进制文件binary file的字节流转换为对象
JSON: 文本序列化格式a text serialization format,输出一个Unicode文本, 人类可读(human-readable)
而pickle是二进制的序列化文件,a relatively compact binary representation, 人类不可读,pickle只能用于Python(Python-specific)。
第一次用Python的pickle处理数据文件,这次只是涉及读取数据,把数据集(dat文件)解析成numpy数组,方便在Python里面进行后续处理。对pickle不熟悉,所以一直没找到debug的门路和关键方向,实际上还是报错的字面意思,就是编码格式不对,我还舍近求远搞了好多不必要的幺蛾子,,,
不算debug吧, 是想用Python读入一批.dat数据,一直没成功,结果竟然倒腾了一下午还加半个晚上,把网上的博客,百科翻了个底朝天!!!!像每回debug一样,中间再次开始质疑自己智商,这TMD还能搬个啥砖???
幸好最后终于算是解决了,还以为要搞上一两天呢,还好还好
最终正确代码:
# coding: utf-8
import pickle
import numpy as np
# 读入数据
x = pickle.load(open('D:\ProgramData\Anaconda3\MyData\data_preprocessed_python\s01.dat', 'rb'),encoding='latin1')
for key in x.keys():
print(key)
print(x['labels'].shape)
print(x['data'].shape)
输出结果
labels
data
(40, 4)
(40, 40, 8064)
关键就在于pickle.load()那行代码里面最后的encoding参数,应该输入latin1,默认的是ascii, 但会一直报错
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 0: ordinal not in range(128)
结果我嫌英文看着烦,看个大概几句就跑去各种搜索,执行各种事倍功半的尝试:
b'labels'
b'data'
然后想用某博客的方法改变字典变量的键名不改值,结果由于涉及到字符串的单双引号,改不成功
# coding: utf-8
import pickle
import numpy as np
# 读入数据
x = pickle.load(open('D:\ProgramData\Anaconda3\MyData\data_preprocessed_python\s01.dat', 'rb'), encoding='bytes')
for key in x.keys():
print(key)
x['data'] = x.pop(" b'data' ")
报错:
b'labels'
b'data'
x['data'] = x.pop(" b'data' ")
KeyError: " b'data' "
x = np.fromfile('D:\ProgramData\Anaconda3\MyData\data_preprocessed_python\s01.dat', dtype=int)
总结:
对函数/模块不了解先仔细看完官方文档,再去搜索网上的零七八碎的资源,有时候网上资源很好使,但有的时候遇到的难题在网上并不能找到很多共鸣,而且有一些资源用的是python2,结果引入很多误会浪费时间,这次问题虽然花了不少时间,但是是由于自己方法不当导致的