用 zipfile.zipfile 的 getinfo() 直接获取 zipinfo 对象可读取元数据,无需解压;zipinfo 包含 filename、date_time(需解包为 datetime)、file_size 等字段;注意路径区分大小写、编码及 zip 时区无自动转换。

用 zipfile.ZipFile 读取文件而不解压
直接打开 ZIP 包并访问特定成员的元数据,不需要先解压到磁盘。关键在于用 getinfo() 或遍历 filelist 找到目标 ZipInfo 对象——它自带完整元数据字段。
常见错误是试图用 open() 或 read() 去“读内容”再解析时间戳或大小,其实完全没必要:元数据就存在索引里。
-
ZipInfo.filename:带路径的原始文件名(注意可能含/) -
ZipInfo.date_time:元组格式(year, month, day, hour, minute, second),不是datetime对象 -
ZipInfo.file_size和ZipInfo.compress_size:原始大小和压缩后大小(字节) -
ZipInfo.CRC:校验码,可用于完整性验证
按文件名精确匹配 ZipInfo 成员
ZIP 包内文件名区分大小写,且路径分隔符固定为 /(即使在 Windows 上创建)。用 namelist() 查找时,必须严格匹配,否则会漏掉或报 KeyError。
推荐用 getinfo() 而非 open(),因为后者只返回文件句柄,不提供元数据;而 getinfo() 直接返回 ZipInfo 实例。
- 安全做法:
try: info = zf.getinfo("data/config.json"),捕获KeyError - 避免用
for f in zf.filelist:+if f.filename == ...,效率低且易忽略编码问题 - 如果文件名含中文或特殊字符,确保 ZIP 是用默认编码(通常是 CP437 或 UTF-8)创建的;Python 3.11+ 默认尝试 UTF-8 fallback,老版本需手动指定
ZipFile(..., metadata_encoding="utf-8")
date_time 转成 Python datetime 的坑
ZipInfo.date_time 是六元组,不是标准时间对象。直接传给 datetime() 会出错,因为缺少 tzinfo 且 ZIP 规范不存及时区——它始终是本地时间(创建时系统时区),且无夏令时修正。
- 正确转换:
datetime(*info.date_time)(注意解包) - 但要注意:如果 ZIP 在东八区创建,你在北京机器上读出来就是北京时间;若在西八区创建,同样调用会得到 PST 时间——Python 不做自动时区推断
- 如需统一处理,建议记录创建环境时区,或改用
timestamp = time.mktime(info.date_time + (0, 0, -1))再转datetime.fromtimestamp()(仅限本地时区场景)
大 ZIP 包里快速定位单个文件的性能技巧
对几百 MB 甚至 GB 级 ZIP,调用 namelist() 会一次性加载所有文件名到内存,而 getinfo() 内部仍需扫描中央目录。真正高效的方式是跳过全量扫描,直接查中央目录结构——但标准库不暴露该接口。
实际可优化点有限,但以下能减少开销:
- 用
ZipFile(..., allowZip64=True)避免大包报错 - 避免反复打开关闭:复用
ZipFile实例,尤其在循环中查多个文件时 - 若只需文件大小和时间戳,别调用
zf.read(name)——它会解压内容,纯属浪费 CPU 和内存 - 极端场景(如日志分析工具),可考虑用
py7zr或libarchive-c替代,它们对元数据访问更底层、更快
真正难的不是“怎么取”,而是“怎么确定取的是对的”:路径是否标准化、编码是否一致、时区是否隐含、ZIP 是否损坏——这些比代码多一行少一行影响更大。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











