【发布时间】:2010-11-21 03:23:35
【问题描述】:
python 中可用的最短哈希(以文件名可用的形式,如十六进制摘要)是什么?我的应用程序想要为某些对象保存 缓存文件。对象必须具有唯一的 repr() 以便它们用于“播种”文件名。我想为每个对象(不是很多)生成一个可能唯一的文件名。它们不应该发生冲突,但如果它们发生冲突,我的应用程序将缺少该对象的缓存(并且必须重新索引该对象的数据,这对应用程序来说成本很小)。
因此,如果发生一次冲突,我们会丢失一个缓存文件,但缓存所有对象所收集的节省使应用程序启动速度更快,所以这并不重要。
现在我实际上正在使用 abs(hash(repr(obj)));没错,就是字符串哈希!还没有发现任何冲突,但我想要一个更好的哈希函数。 hashlib.md5 在 python 库中可用,但如果放入文件名,则 hexdigest 真的很长。具有合理抗碰撞性的替代品?
编辑:
用例是这样的:
数据加载器获取数据承载对象的新实例。独特的类型有独特的代表。因此,如果存在 hash(repr(obj)) 的缓存文件,我将取消该缓存文件并将 obj 替换为未腌制的对象。如果发生冲突并且缓存是错误匹配,我会注意到。因此,如果我们没有缓存或存在错误匹配,我会改为初始化 obj(重新加载其数据)。
结论 (?)
python 中的str 哈希可能已经足够好了,我只是担心它的抗碰撞性。但是,如果我可以用它散列2**16 对象,那就足够了。
我发现了如何获取十六进制哈希(来自任何哈希源)并使用 base64 紧凑地存储它:
# 'h' is a string of hex digits
bytes = "".join(chr(int(h[i:i+2], 16)) for i in xrange(0, len(h), 2))
hashstr = base64.urlsafe_b64encode(bytes).rstrip("=")
【问题讨论】:
-
为什么要关心文件名的长度?这根本不重要,除非您使用的是愚蠢的文件系统
-
很难看。所有的程序员都想用更多的东西表达更少的东西,而我知道我可以,一个完整的加密哈希是多余的。
-
在最后的示例中,对于 python hashlib 哈希,您当然可以使用 bytes = (..).digest()。
-
您不应该使用内置哈希,因为它不能保证在会话(或体系结构,尽管如果所有缓存文件都存储在本地,这可能与您的情况无关)是持久的。事实上,从 Python 3.3 开始,它保证对字符串是随机的。您应该考虑使用手写函数,例如this。