简体   繁体   English

酱菜堆没有唯一的代表? 创建Python字典的唯一序列化

[英]Pickle dumps has no unique representation? Create a unique serialization of Python dictionary

I'm writing a caching script, which takes a certain object and stores it as a file. 我正在编写一个缓存脚本,该脚本接受某个对象并将其存储为文件。 The object's initial parameters are supposed to be used as filename (because I want different caches for different initial parameters). 该对象的初始参数应该用作文件名(因为我想为不同的初始参数使用不同的缓存)。

I thought serialization was a bijection, so my plan was to serialize the (parameter) dictionary, create a hex using hashlib.sha224().hexdigest() and use the first XX characters as a filename. 我认为序列化是一个双射,所以我的计划是序列化(参数)字典,使用hashlib.sha224().hexdigest()创建一个十六进制,并使用前XX个字符作为文件名。 However, repeatedly serializing the dictionary using pickle.dumps yields different serializations... 但是,使用pickle.dumps重复序列化字典pickle.dumps产生不同的序列化...

I want to serialize a dictionary: 我想序列化字典:

attr = {'I': 1,
 'LBar': 1,
 'N': 50,
 'ProdMatch': 1,
 'T': 10,
 'alpha': 0.5,
 'b': 0.1,
 'c': 0.1,
 'delta': 0.1,
 'deltaN': 0.02,
 'deltaT': 10.0,
 'logspace': False,
 'nT': 1,
 'period': 'quarterly',
 'rho': 0.03,
 'sigma': 0.5}

ser = pickle.dumps(attr)
print(pickle.loads(ser))

Which gives me as output the input dictionary and the following string. 这给了我输入字典和以下字符串作为输出。

b'\x80\x03}q\x00(X\x01\x00\x00\x00cq\x01G?\xb9\x99\x99\x99\x99\x99\x9aX\x01\x00\x00\x00Nq\x02K2X\x01\x00\x00\x00Tq\x03K\nX\x05\x00\x00\x00deltaq\x04G?\xb9\x99\x99\x99\x99\x99\x9aX\x06\x00\x00\x00deltaNq\x05G?\x94z\xe1G\xae\x14{X\x06\x00\x00\x00deltaTq\x06G@$\x00\x00\x00\x00\x00\x00X\x05\x00\x00\x00alphaq\x07G?\xe0\x00\x00\x00\x00\x00\x00X\x03\x00\x00\x00rhoq\x08G?\x9e\xb8Q\xeb\x85\x1e\xb8X\x04\x00\x00\x00LBarq\tK\x01X\x01\x00\x00\x00bq\nG?\xb9\x99\x99\x99\x99\x99\x9aX\x06\x00\x00\x00periodq\x0bX\t\x00\x00\x00quarterlyq\x0cX\x02\x00\x00\x00nTq\rK\x01X\x01\x00\x00\x00Iq\x0eK\x01X\t\x00\x00\x00ProdMatchq\x0fK\x01X\x05\x00\x00\x00sigmaq\x10G?\xe0\x00\x00\x00\x00\x00\x00X\x08\x00\x00\x00logspaceq\x11\x89u.'

I then restart my Python interpreter and run the same script: 然后,我重新启动Python解释器并运行相同的脚本:

b'\x80\x03}q\x00(X\x05\x00\x00\x00deltaq\x01G?\xb9\x99\x99\x99\x99\x99\x9aX\x05\x00\x00\x00alphaq\x02G?\xe0\x00\x00\x00\x00\x00\x00X\x04\x00\x00\x00LBarq\x03K\x01X\x01\x00\x00\x00Iq\x04K\x01X\x02\x00\x00\x00nTq\x05K\x01X\x01\x00\x00\x00bq\x06G?\xb9\x99\x99\x99\x99\x99\x9aX\x01\x00\x00\x00Tq\x07K\nX\x03\x00\x00\x00rhoq\x08G?\x9e\xb8Q\xeb\x85\x1e\xb8X\x01\x00\x00\x00cq\tG?\xb9\x99\x99\x99\x99\x99\x9aX\t\x00\x00\x00ProdMatchq\nK\x01X\x06\x00\x00\x00periodq\x0bX\t\x00\x00\x00quarterlyq\x0cX\x06\x00\x00\x00deltaNq\rG?\x94z\xe1G\xae\x14{X\x06\x00\x00\x00deltaTq\x0eG@$\x00\x00\x00\x00\x00\x00X\x05\x00\x00\x00sigmaq\x0fG?\xe0\x00\x00\x00\x00\x00\x00X\x08\x00\x00\x00logspaceq\x10\x89X\x01\x00\x00\x00Nq\x11K2u.'

These are different serializations. 这些是不同的序列化。 Pickle is not broken, as loads() will regenerate the initial dictionary, but I can't have this behavior for my purposes, as it will not find a stored file if it searches under a different hash. 泡菜没有坏,因为loads()会重新生成初始字典,但是出于我的目的,我不能有这种行为,因为如果它在不同的哈希下搜索,它将找不到存储的文件。 I also tried dill.dumps , with the same result. 我还尝试了dill.dumps ,结果相同。

Dictionaries prior to Python 3.6 don't have a specific, repeatable order. Python 3.6之前的字典没有特定的可重复顺序。 In fact, in Python 3 up to Python 3.5 their order is randomize. 实际上,在Python 3到Python 3.5中,它们的顺序是随机的。

Try sorting the items: 尝试对项目进行排序:

import pickle
ser = pickle.dumps(sorted(attr.items()))
print(dict(pickle.loads(ser)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM