在python中生成文件的校验和

时间:2016-11-04 08:24:29

标签: python

这个问题已在本网站上被多次询问和回答,但由于一些模糊的原因,没有人提出相对简单的(在我看来),更简洁,可能更优雅的解决方案。也许是因为解决方案实际上很糟糕,但这是我想要弄清楚的,如果它不好,那么我想知道如何以及为什么。 其中一个最受欢迎的答案是:

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')中的前缀迭代字节对象。这样做有什么不对?

1 个答案:

答案 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哈希值。