在python中生成文件的校验和

在python中生成文件的校验和,python,Python,这个问题已经在这个网站上被问过很多次了,但由于一些模糊的原因,没有人提出一个相对简单(在我看来),更简洁,可能更优雅的解决方案。也许是因为这个解决方案实际上不好,但这正是我想弄明白的,如果它不好,那么我想知道如何以及为什么。 最流行的答案之一是: def md5(fname): hash_md5 = hashlib.md5() with open(fname, "rb") as f: for chunk in iter(lambda: f.read(4096), b""):

这个问题已经在这个网站上被问过很多次了,但由于一些模糊的原因,没有人提出一个相对简单(在我看来),更简洁,可能更优雅的解决方案。也许是因为这个解决方案实际上不好,但这正是我想弄明白的,如果它不好,那么我想知道如何以及为什么。 最流行的答案之一是:

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()

方便的是,迭代打开的文件句柄会给我们一系列行,因此我们可以使用
open(fname,'rb')
中的'b'前缀来迭代字节对象。这样做有什么不对?

V博士在评论中说的是正确的

对f中的块使用
操作以
b'\n
'==
b'\x0A'
结尾的块。这使得文本文件的块大小非常小,而典型二进制文件的块大小完全不可预测:二进制文件可能不包含任何
0A
字节。当f中的chunk发生这种情况时:只需将整个文件读入单个chunk

4k的块大小应该可以,但您可以尝试64k或128k的块大小,看看这是否可以提高速度。在简单的数据复制测试(使用
dd
)中,我发现使用较大的块大小没有什么好处;请记住,现代操作系统擅长文件缓冲和缓存。OTOH,我在运行一台相当旧的32位单核机器

关于散列大文件的主题,您可能对使用OpenSSL加密库对大文件执行SHA256散列感兴趣。这个程序的特点是它是可恢复的:您可以随时停止它,当您重新启动它时,它将继续散列过程


这将使用
hashlib
同时计算文件的MD5和SHA256哈希值。

这可能是您处理的文件类型的问题,特别是它实际上是ascii文件还是二进制文件。原始版本提供了对块大小的更多控制,而您的版本则取决于是否需要换行。另外,为了处理大文件,我一次不只是使用4K数据,而是至少使用100K,以确保“分块”中没有明显的开销。我曾经有过使用zip模块的经验,现在100K算不了什么了。@V博士,我明白了,我几乎同意你说的每一句话,但据我所知,它适用于所有类型的文件。@weeCoder尝试创建一个不包含
\x0a
字节的大文件,然后看看。。。f中chunk的
降级为
chunk=f.read()
将整个文件读入内存。@PM2Ring噢,谢谢,这基本上回答了我的问题。如果你认为它对其他人有用,你应该把它作为一个答案贴出来。