必须分块读取并用hashlib.md5().update()增量计算,因open().read()会一次性加载大文件导致内存溢出;需以rb模式打开、单次初始化哈希对象、使用8192字节等固定块大小循环读取更新。

用 hashlib.md5() 分块读取大文件计算哈希
直接 open().read() 整个大文件会爆内存,必须分块读。Python 的 hashlib.md5() 支持增量更新,这是关键。
- 每次读取固定大小(如
8192字节),调用update()累积哈希状态 - 避免把整个文件内容塞进内存,哪怕文件是几个 GB 也能稳定运行
- 别用
hashlib.md5(file_content).hexdigest()—— 这种写法隐含全量加载,是典型踩坑点
def calc_md5(filepath):
h = hashlib.md5()
with open(filepath, "rb") as f:
while chunk := f.read(8192):
h.update(chunk)
return h.hexdigest()
为什么不能只靠文件名或 os.stat().st_size 去重?
文件名可能重复、大小可能撞车,但内容不同 —— 这类“伪重复”会导致逻辑错误,比如跳过本该处理的新版本配置文件。
-
os.path.getsize()相同 ≠ 内容相同:两个 10MB 的日志文件,结构和数据很可能完全不同 - 改名不改内容?文件名变了但哈希不变,仍应视为重复
- 哈希是内容指纹,唯一可靠依据;其他字段只能辅助快速筛选(比如先比大小再算哈希)
把 MD5 存哪?用字典缓存还是 SQLite?
单次脚本运行用内存字典足够;长期服务或跨进程需持久化,SQLite 比纯文本更可靠。
- 临时去重:用
dict存{md5_hex: filepath},查重 O(1),但重启即丢 - 多进程/多天运行:建 SQLite 表,字段至少包含
md5 TEXT UNIQUE和filepath TEXT,避免并发写冲突 - 别用 JSON 文件存哈希列表 —— 并发写入易损坏,且无原子性保障
注意 hashlib.md5() 在不同 Python 版本下的一致性
MD5 算法本身是标准的,但如果你在 Windows 和 Linux 间共享哈希值,要确认文件打开模式和换行符没干扰。
- 务必用
"rb"模式打开 —— 文本模式会触发自动换行符转换(\r\n→\n),导致哈希不一致 - Python 3.9+ 对空文件的
md5()结果与旧版完全一致,无需额外兼容 - 如果文件路径含中文或特殊字符,
open()默认编码不影响二进制读取,不用管
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











