在我的脚本中,我使用大而复杂的对象(包含自定义类型的字符串,字典和类对象的多维列表)。我需要复制,pickle(缓存)和unpickle,以及通过MPI
接口在子进程之间发送。在某些方面,我怀疑数据传输没有错误,即最后我有相同的对象。
因此,我想计算其哈希值或其他类型的指纹。我知道有例如hashlib
库;但是,它在对象类型方面受到限制:
>>> import hashlib
>>> a = "123"
>>> hashlib.sha224(a.encode()).hexdigest()
'78d8045d684abd2eece923758f3cd781489df3a48e1278982466017f'
>>> a = [1, 2, 3]
>>> hashlib.sha224(a).hexdigest()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object supporting the buffer API required
因此,问题是:是否有一些类似的函数可以处理任何类型的对象?
答案 0 :(得分:1)
pickle.dumps(...)
返回一个字符串,它是一个可哈希的对象。您可以按照以下方式执行此操作
import pickle
a=[1,2,3,4]
h=pickle.dumps(a)
print hash(h)
# or like this
from hashlib import sha512
print sha512(h).hexdigest()
c=pickle.loads(h)
assert c==a
答案 1 :(得分:1)
一种选择是递归地将结构的所有元素转换为可混合的对应物,即列入元组,dicts和对象到frozensets,然后简单地将hash()
应用于整个事物。举例说明:
def to_hashable(s):
if isinstance(s, dict):
return frozenset((x, to_hashable(y)) for x, y in s.items())
if isinstance(s, list):
return tuple(to_hashable(x) for x in s)
if isinstance(s, set):
return frozenset(s)
if isinstance(s, MyObject):
d = {'__class__': s.__class__.__name__}
d.update(s.__dict__)
return to_hashable(d)
return s
class MyObject:
pass
class X(MyObject):
def __init__(self, zzz):
self.zzz = zzz
my_list = [
1,
{'a': [1,2,3], 'b': [4,5,6]},
{1,2,3,4,5},
X({1:2,3:4}),
X({5:6,7:8})
]
print hash(to_hashable(my_list))
my_list2 = [
1,
{'b': [4,5,6], 'a': [1,2,3]},
{5,4,3,2,1},
X({3:4,1:2}),
X({7:8,5:6})
]
print hash(to_hashable(my_list2)) # the same as above