为了账号安全,请及时绑定邮箱和手机立即绑定

生成文件的MD5校验和

生成文件的MD5校验和

慕斯709654 2019-10-05 10:51:42
是否有任何简单的方法来生成(和检查)Python中文件列表的MD5校验和?(我正在处理一个小程序,我想确认文件的校验和)。
查看完整描述

3 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

您可以使用hashlib.md5()


请注意,有时您将无法在内存中容纳整个文件。在这种情况下,您将必须顺序读取4096个字节的块并将其提供给Md5函数:


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

注意: 如果只需要使用打包字节use ,hash_md5.hexdigest()则将返回摘要的十六进制字符串表示形式return hash_md5.digest(),因此您不必转换回去。


查看完整回答
反对 回复 2019-10-05
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

我显然没有添加任何根本上没有新的内容,而是在我要评论状态之前添加了此答案,并且代码区域使事情更加清晰了-无论如何,特别是要从Omnifarious的答案中回答@Nemo的问题:


我碰巧在考虑校验和(在这里专门寻找有关块大小的建议),并且发现此方法可能比您期望的要快。以最快的(但相当典型值)timeit.timeit或/usr/bin/time从每个执行校验和的约文件的几种方法的结果。11MB:


$ ./sum_methods.py

crc32_mmap(filename) 0.0241742134094

crc32_read(filename) 0.0219960212708

subprocess.check_output(['cksum', filename]) 0.0553209781647

md5sum_mmap(filename) 0.0286180973053

md5sum_read(filename) 0.0311000347137

subprocess.check_output(['md5sum', filename]) 0.0332629680634

$ time md5sum /tmp/test.data.300k

d3fe3d5d4c2460b5daacc30c6efbc77f  /tmp/test.data.300k


real    0m0.043s

user    0m0.032s

sys     0m0.010s

$ stat -c '%s' /tmp/test.data.300k

11890400

因此,对于11MB的文件来说,Python和/ usr / bin / md5sum大约都需要30毫秒。相关md5sum功能(md5sum_read在上面的清单中)与Omnifarious的功能非常相似:


import hashlib

def md5sum(filename, blocksize=65536):

    hash = hashlib.md5()

    with open(filename, "rb") as f:

        for block in iter(lambda: f.read(blocksize), b""):

            hash.update(block)

    return hash.hexdigest()

当然,这些都是单次运行的(mmap至少进行几十次运行时,总是总是更快一些),并且f.read(blocksize)在缓冲区用完后,我的通常会获得额外的收入,但是它是相当可重复的,并且md5sum在命令行上显示不一定比Python实现要快...


编辑:抱歉,很长的延迟,已经有一段时间没有看到了,但是为了回答@EdRandall的问题,我将写下一个Adler32实现。但是,我还没有运行基准测试。它基本上与CRC32相同:除了初始化,更新和摘要调用外,其他所有操作都是zlib.adler32()调用:


import zlib

def adler32sum(filename, blocksize=65536):

    checksum = zlib.adler32("")

    with open(filename, "rb") as f:

        for block in iter(lambda: f.read(blocksize), b""):

            checksum = zlib.adler32(block, checksum)

    return checksum & 0xffffffff

请注意,此操作必须以空字符串开头,因为从零开始的Adler和确实确实不同,而对于,它们的总和""是1-CRC可以0代替。AND需要使用-ing使其成为32位无符号整数,以确保其在Python版本之间返回相同的值。


查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 634 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信