我正在尝试加载一个腌制的字典,但是不断出现诸如此类的属性错误
TypeError: a bytes-like object is required, not '_io.BufferedReader'
下面是读取和写入泡菜对象的代码。我将带有python 2.7.12的腌制对象转储到linux工作站上。数据使用python 3.6.4传输到Mac,在其中执行readTrueData()导致上述错误。
def readTrueData(name):
fName = str('trueData/'+name+'.pkl')
f = open(fName,'rb')
# print(f)
# print(type(f))
pC = pickle.loads(f)
return pC
def storeTrueData(atomicConfigs, name):
import quippy
storeDic = {}
#rangeKeys = len(atomicConfigs)
#print(rangeKeys)
qTrain = quippy.AtomsList(atomicConfigs)
print(len(qTrain))
rangeKeys = len(qTrain)
print(rangeKeys)
for i in range(rangeKeys):
#configConsidered = atomicConfigs[i]
trueForce = np.array(qTrain[i].force).T
storeDic[i] = trueForce
f = open("trueData/"+ name + ".pkl", "wb")
pickle.dump(storeDic, f)
f.close()
return None
根据评论中提到的建议,我更改了代码,如下所示
a。)pC = pickle.load(f)
b。)pC = pickle.loads(f.read())
在这两种情况下,我都会遇到以下错误
UnicodeDecodeError: 'ascii' codec can't decode byte 0x87 in position 1: ordinal not in range(128)
答案 0 :(得分:1)
如果以这种方式使用pickle.load(...)
,则需要使用open
进行读取。
答案 1 :(得分:1)
varchar(MAX)
是您想要的,但您确实应该使用with
context:
pC = pickle.loads(f.read())
这将确保您的文件正确关闭,尤其是因为您的代码在函数中没有with open(fName, 'rb') as f:
pC = pickle.loads(f.read())
。
答案 2 :(得分:1)
您的第一个问题是由参数类型与所选的load*
方法之间的不匹配引起的; loads
期望bytes
个对象,load
期望文件对象本身。将文件对象传递给loads
是导致您出错的原因。
您的其他问题是由于numpy
和datetime
类型的跨版本兼容性问题引起的; Python 2腌制str
且没有指定的编码,但是Python 3必须使用已知的编码(或'bytes'
来腌制它们(以获得原始的bytes
而不是str
)。对于numpy
和datetime
类型,you're required to pass encoding='latin-1'
:
可选的关键字参数是fix_imports,编码和错误,用于控制对Python 2生成的pickle流的兼容性支持。如果fix_imports为true,pickle将尝试将旧的Python 2名称映射到Python中使用的新名称。 3.编码和错误告诉pickle如何解码Python 2腌制的8位字符串实例;它们分别默认为“ ASCII”和“ strict”。编码可以是“字节”,以将这些8位字符串实例读取为bytes对象。要解开NumPy数组和Python 2腌制的日期时间,日期和时间实例,需要使用encoding ='latin1'。
无论如何,解决方法是更改:
def readTrueData(name):
fName = str('trueData/'+name+'.pkl')
f = open(fName,'rb')
# print(f)
# print(type(f))
pC = pickle.loads(f)
return pC
收件人:
def readTrueData(name):
fName = str('trueData/'+name+'.pkl')
with open(fName, 'rb') as f: # with statement avoids file leak
# Match load with file object, and provide encoding for Py2 str
return pickle.load(f, encoding='latin-1')
出于正确性和性能方面的考虑,我还建议在Python 2计算机上将pickle.dump(storeDic, f)
更改为pickle.dump(storeDic, f, protocol=2)
,以便使用更现代的pickle协议生成流,该协议可以有效地对{ {1}}数组等等。协议0是Python 2的默认设置,它不能使用每个字节的最高位(它与ASCII兼容),这意味着协议2中的原始二进制数据急剧膨胀,需要大量的比特摆动,协议2可以将其原始转储。协议2也是唯一有效地腌制新样式类的Py2协议,并且是唯一可以完全腌制某些类型的实例(使用numpy
/ __slots__
等的实例的Py2协议。) >
我还建议脚本以:
开头__new__
与Python 2一样,try:
import cPickle as pickle
except ImportError:
import pickle
是在纯Python中实现的,它速度慢且无法使用某些更高效的pickle代码。在Python 3上,pickle
消失了,但是cPickle
被自动加速了。在那和使用协议2之间,在Python 2机器上进行酸洗应该更快地运行,并产生更小的泡菜。