zipfile.is_zipfile()仅检测文件头和末端记录,返回False表示非ZIP或中央目录损坏,但无法识别CRC校验失败等逻辑损坏;testzip()可深度验证成员完整性但耗时且不修复;严重结构损坏需用7z或zip -F等外部工具修复。

用 zipfile.is_zipfile() 快速判断 ZIP 是否损坏
直接调用 zipfile.is_zipfile() 是最轻量的检测方式,它不加载内容,只读取文件头和末端记录。返回 False 通常意味着文件不是 ZIP 格式,或中央目录结构已损坏(比如被截断、写入中途失败)。
注意:这个函数无法识别“逻辑损坏”——例如 CRC 校验失败但文件头完好的 ZIP(常见于传输中断后手动重命名的 .zip 文件)。这类包 is_zipfile() 会返回 True,但后续解压时抛出 BadZipFile 或 zlib.error。
- 对大文件也很快,适合批量预筛
- 不能替代完整校验,仅作第一道过滤
- 若路径含中文或特殊字符,确保传入
str类型(pathlib.Path对象需先转str)
用 zipfile.ZipFile().testzip() 检查内部文件完整性
testzip() 会逐个读取每个成员的压缩数据并验证 CRC 和解压可行性,是真正意义上的“深度检测”。它返回第一个损坏成员的名称,或 None 表示全部通过。
关键点在于:它不修复,只报错;且一旦遇到损坏项就立即返回,不会继续扫描其余文件。这意味着你得自己循环重试或捕获异常来定位全部问题。
立即学习“Python免费学习笔记(深入)”;
- 必须用
try/except包裹,因为损坏严重时可能直接抛出BadZipFile - 耗时与 ZIP 内容大小正相关,含大量小文件时比单个大文件更慢
- 某些加密 ZIP 会在此阶段触发
RuntimeError: File is encrypted,需提前用pwd参数处理
用 zipfile.ZipFile 手动重建 ZIP(绕过损坏条目)
Python 标准库不提供“自动修复”功能,但你可以用 ZipFile 读取正常成员 + ZipFile(mode='w') 写入新包,实现“剔除损坏项后重建”。这本质是数据抢救,不是修复原始文件。
操作核心是跳过 testzip() 报出的损坏项,或捕获 read() 异常后忽略该成员。重建后的新 ZIP 不再包含损坏引用,但原始损坏文件内容已不可恢复。
- 务必用二进制模式打开源文件:
with open('bad.zip', 'rb') as f: - 写入新 ZIP 时设置
compression=zipfile.ZIP_DEFLATED,否则默认为无压缩,体积暴涨 - 原 ZIP 中的注释、跨卷信息、AES 加密等高级特性无法保留
- 若损坏的是中央目录本身(而非某个文件),
ZipFile构造就会失败,此时只能靠第三方工具如7z命令行尝试恢复
何时该放弃 Python 自救,转向外部工具
当 zipfile 模块在构造对象时就抛出 BadZipFile: File is not a zip file 或 IOError: invalid start of central directory,基本说明 ZIP 的核心结构(如 EOCD 记录)已丢失或错位。Python 无力重建这种底层损坏。
这时应优先尝试命令行工具:7z r archive.zip(reconstruct 模式)能扫描原始字节流,尝试找回可识别的文件片段;zip -F(fix)则专用于修复因截断导致的中央目录缺失。
-
7z对部分损坏 ZIP 的恢复能力远超 Python 标准库 -
zip -F只适用于“末尾丢失”的情况,对头部损坏无效 - 所有外部修复操作前,务必先备份原始文件——修复过程可能覆盖原数据
真正棘手的情况是:ZIP 被部分覆写(比如磁盘坏道导致中间字节损坏),此时连 7z 也可能只恢复出碎片。这种损坏没有通用解法,只能靠备份或专业数据恢复服务。


















