如何在Python中创建文件的校验和

5 投票
3 回答
15722 浏览
提问于 2025-04-18 14:00

我想给一个文件生成一个校验和,并把这个校验和保存成一个文件。这样的话,我就可以监控这个文件,如果校验和发生变化,我就可以采取一些行动。

这是校验和的内容:

对于 test.txt 文件:

contents: a
checksum: dd18bf3a8e0a2a3e53e2661c7fb53534

我编辑了这个文件:

contents: aa
checksum: dd18bf3a8e0a2a3e53e2661c7fb53534

这是我的代码:

python -c 'import hashlib;print hashlib.md5("test.txt").hexdigest()'

为什么这些校验和是一样的呢?

3 个回答

0

hashlib中的核心哈希函数是用来处理字符串内容的,而不是用来打开和读取文件名的。所以正如James所说,你在两种情况下哈希的都是同一个值'text.txt'

Python 3.11+

如果你只使用Python 3.11及以上版本,有一个新选项可以使用:hashlib.file_digest()。这个函数可以接受一个文件对象和一个哈希函数,或者哈希函数的名称。你之前尝试的做法可以这样实现:

import hashlib
with open('text.txt', 'rb') as file:
    print(hashlib.file_digest(file, 'md5').hexdigest())

Python 2.7-3.10+

虽然hashlib.file_digest()在所有支持的Python版本上要到2026年10月才会可用,但我们仍然可以深入了解,看看如何用bytearraymemoryview来制作一个更好的md5sum()版本,而不是使用iter(lambda: f.read())

import hashlib

def md5sum(filename, _bufsize=2**18):
    digest = hashlib.md5()
    
    buf = bytearray(_bufsize)
    view = memoryview(buf)
    with open(filename, 'rb') as file:
        while True:
            size = file.readinto(buf)
            if size == 0:
                break  # EOF
            digest.update(view[:size])
    
    return digest.hexdigest()
7

为什么这些校验和是一样的?

因为你计算的是同一个文件 test.txt 的哈希值。

这里有一个通用工具(它是一个类似于许多Linux和UNIX平台上常见的 md5sum 命令行工具的克隆),可以很好地处理大文件。

md5sum.py:

#!/usr/bin/env python

"""Tool to compuete md5 sums of files"""

import sys
from hashlib import md5


def md5sum(filename):
    hash = md5()
    with open(filename, "rb") as f:
        for chunk in iter(lambda: f.read(128 * hash.block_size), b""):
            hash.update(chunk)
    return hash.hexdigest()


def main():
    if len(sys.argv) < 2:
        print "Usage: md5sum <filename>"
        raise SystemExit(1)

    print md5sum(sys.argv[1])


if __name__ == "__main__":
    main()

大量借鉴自: https://bitbucket.org/prologic/tools/src/tip/md5sum

3

你可以试着查看一下 hashlib.md5() 这个链接。

import hashlib
[(fname, hashlib.md5(open(fname, 'rb').read()).digest()) for fname in fnamelst]

撰写回答