zipfile可遍历zip包并按后缀筛选提取,需用namelist()或infolist()遍历、endswith()或suffix判断,注意路径分隔符为/、编码问题及异常处理。

用 zipfile 遍历 ZIP 包并筛选后缀文件
Python 标准库 zipfile 足够应付大多数 ZIP 批量提取需求,无需额外安装。关键不是“解压全部”,而是先遍历成员、按后缀过滤、再逐个提取。
常见错误是直接调用 extractall() 后再删文件——既浪费 I/O,又可能误删同名非目标文件。
-
ZipFile.namelist()返回所有路径字符串,可直接用.endswith('.txt')或pathlib.Path(name).suffix in {'.log', '.csv'}判断 - 注意路径分隔符:ZIP 内部统一用
/,即使在 Windows 上生成的包也如此;不要用os.path处理内部路径 - 若压缩包含嵌套目录,
name是完整路径(如'data/2024/report.pdf'),提取时extract()会自动重建目录结构
处理 RAR / 7z 等非 ZIP 格式必须换工具
zipfile 只支持 ZIP、JAR、DOCX(本质 ZIP)等基于 ZIP 格式的文件,对 RAR、7z、ACE 等完全无效。尝试打开会抛出 BadZipFile 或静默失败。
真实场景中,混合压缩格式很常见。稳妥做法是先用 file 命令或魔数检测类型(Python 可用 python-magic),再分发处理:
- RAR:需系统已安装
unrar命令行工具,用subprocess.run(['unrar', 'x', '-o+', archive, '*.log'], cwd=dst_dir) - 7z:依赖
7z命令,参数为['7z', 'x', archive, '-o'+dst_dir, '-r', '*.json'];注意-r表示递归匹配子目录 - 不建议用
pyunpack或patool:它们只是命令行工具包装器,仍需宿主机安装对应解压程序,且错误反馈模糊
提取时保留原始目录结构还是扁平化存放?
默认 extract() 会还原 ZIP 内路径结构,但有时你只想拿所有 .py 文件到一个文件夹里,不管它原来在哪层目录下。
这时不能只改写文件名,还要防止重名覆盖:
- 扁平化提取:对每个匹配的
name,用os.path.basename(name)取文件名,再用计数器或哈希去重(如f"{i}_{basename}") - 注意编码问题:某些老 ZIP 用 GBK 存中文路径,
ZipFile默认按 UTF-8 解码会报UnicodeDecodeError;可传参ZipFile(archive, 'r', metadata_encoding='gbk')(Python 3.11+) - 大包慎用
namelist()全加载:超万级文件时内存压力明显;可用infolist()+ 按需检查info.filename,效果相同但更省内存
批量处理多个压缩包时的异常控制要点
实际批量任务中,部分压缩包损坏、密码保护、权限不足很常见。硬抛异常会导致整个流程中断。
必须为每个包单独 try/catch,并记录日志而不是打印堆栈:
- 捕获
zipfile.BadZipFile(非 ZIP 或损坏)、RuntimeError(加密 ZIP 未提供密码)、PermissionError(目标目录不可写) - 加密 ZIP 若知道密码,可用
ZipFile.setpassword(b'pwd'),但仅支持 ZIP 2.0 传统加密,不支持 AES - 别忽略
BrokenPipeError:当输出被重定向(如> /dev/null)而提前终止时触发,属于正常退出信号,不应视为错误
真正容易被忽略的是时间戳还原——extract() 默认不恢复原始修改时间,需手动调用 os.utime() 配合 ZipInfo.date_time,否则日志分析类任务会丢失关键时序信息。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











