这个问题已在本网站上被多次询问和回答,但由于一些模糊的原因,没有人提出相对简单的(在我看来),更简洁,可能更优雅的解决方案。也许是因为解决方案实际上很糟糕,但这是我想要弄清楚的,如果它不好,那么我想知道如何以及为什么。 其中一个最受欢迎的答案是:
def md5(fname):
hash_md5 = hashlib.md5()
with open(fname, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
这是可以理解的 - 我们不想将整个文件加载到内存中,所以我们在迭代器和lambda函数的帮助下以块的形式读取它。很好,很简单。 但是大概我们可以通过如下定义md5sum函数以简单的方式做到这一点:
def md5sum(fname):
md5 = hashlib.md5()
with open(fname, 'rb') as f:
for chunk in f:
md5.update(chunk)
return md5.hexdigest()
方便地,迭代打开的文件句柄给我们一系列的行,所以我们可以使用' b' open(fname, 'rb')
中的前缀迭代字节对象。这样做有什么不对?
答案 0 :(得分:2)
V博士在评论中所说的是正确的。
使用for chunk in f:
对以b'\n
'== b'\x0A'
结尾的块进行操作。这使得文本文件的块大小非常小,而对于典型的二进制文件则完全不可预测:二进制文件可能不包含任何 0A
个字节。当发生这种情况时for chunk in f:
只需将整个文件读入一个块。
那4k块大小应该没问题,但你可以尝试64k或128k的块大小来看看是否能提高速度。在简单的数据复制测试中(使用dd
)我发现使用更大的块大小没什么好处;请记住,现代操作系统擅长文件缓冲&缓存。 OTOH,我正在运行一台相当古老的32位单核机器。
关于散列大文件的主题,您可能对使用OpenSSL加密库对大文件执行SHA256散列的a program I wrote感兴趣。该程序的功能是它可以恢复:您可以随时停止它,当您重新启动它时,它将继续散列过程。
here's one使用hashlib
同时计算文件的MD5和SHA256哈希值。