如何在泡菜中装载物体?

时间:2019-03-05 19:33:18

标签: python pickle

我正在尝试加载一个腌制的字典,但是不断出现诸如此类的属性错误

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)

3 个答案:

答案 0 :(得分:1)

如果以这种方式使用pickle.load(...),则需要使用open进行读取。

来源:https://docs.python.org/3/library/pickle.html

答案 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是导致您出错的原因。

您的其他问题是由于numpydatetime类型的跨版本兼容性问题引起的; Python 2腌制str且没有指定的编码,但是Python 3必须使用已知的编码(或'bytes'来腌制它们(以获得原始的bytes而不是str)。对于numpydatetime类型,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机器上进行酸洗应该更快地运行,并产生更小的泡菜。