Python zipfile.ZipFile.open 怎样按二进制流读取压缩成员
如果只想读取 ZIP 里的一个文件,zipfile.ZipFile.open() 比先解压到临时目录更直接:它按成员名或 ZipInfo 定位对象,返回一个可读取的二进制文件式对象。最稳妥的写法是把外层 ZipFile 和内层返回对象都放进 with,读取时按块消费,文本内容再单独解码。
官方文档:https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile.open
记住三层边界:ZipFile管理压缩包,ZipFile.open()负责定位成员,返回的ZipExtFile负责提供二进制读取接口。不要把它直接当成已经解码好的字符串。
先区分 ZipFile、成员名和 ZipExtFile 的职责
ZipFile 是压缩包容器;name 参数是包内成员名,也可以传入一个 ZipInfo 对象;open() 返回的对象则是本次读取的流。默认读取模式是 r,读取对象按二进制文件接口工作。

这个划分很重要:包对象负责打开和关闭整个归档,流对象负责读取当前成员。文章中的“读取某个文件”实际上是先完成成员定位,再从流对象取得字节。
用 mode='r' 按块读取成员二进制流
对于图片、证书、压缩配置或未知编码的数据,先保留字节最安全。下面的示例只读取指定成员,不把完整压缩包一次性展开到磁盘:
from pathlib import Path
from zipfile import ZipFile
def read_member(zip_path: Path, member_name: str) -> bytes:
# 外层 with 负责关闭 ZIP 容器,内层 with 负责关闭成员流。
with ZipFile(zip_path, mode="r") as archive:
with archive.open(member_name, mode="r") as member:
chunks: list[bytes] = []
while True:
# 分块读取可以避免把大成员的全部内容一次压进内存。
chunk = member.read(64 * 1024)
if not chunk:
break
chunks.append(chunk)
return b"".join(chunks)
这里的 mode="r" 是读取压缩成员,返回对象支持 read()、readline()、迭代和定位等文件式操作。示例为了展示返回值使用了字节列表;如果文件可能很大,更适合在循环中直接把每个块写入另一个二进制流,而不是最后再拼接。
成员名不稳定时改用 ZipInfo
同一个 ZIP 中可能出现重复成员名。此时直接传字符串会让“按名称打开”变得不明确,可以先从 infolist() 得到具体的 ZipInfo,再把对象传给 open():
from zipfile import ZipFile, ZipInfo
def read_first_report(zip_path: str) -> bytes:
# 用 ZipInfo 保留具体条目,而不是只依赖可能重复的名称。
with ZipFile(zip_path, mode="r") as archive:
report: ZipInfo | None = next(
(item for item in archive.infolist() if item.filename.endswith("report.bin")),
None,
)
if report is None:
# 缺少目标成员时,把问题转换成调用方可处理的异常。
raise FileNotFoundError("ZIP 中没有 report.bin")
with archive.open(report, mode="r") as member:
# read() 只负责取得字节,解码或解析应由上一层决定。
return member.read()
如果成员名不存在,定位阶段通常会抛出 KeyError;如果业务希望统一错误语义,可以像示例一样先列举成员并主动抛出更明确的异常。这里仍然没有声称“读取成功”或展示运行输出,代码只是说明调用关系。
把读取、解码和资源关闭分开
ZIP 成员是二进制流,文本文件要在流外再加一层解码。不要用字符串方法替代字节读取,也不要假设所有成员都是 UTF-8:

import io
from zipfile import ZipFile
def read_text_member(zip_path: str, member_name: str, encoding: str = "utf-8") -> str:
# ZipFile.open() 先给出二进制流,再由 TextIOWrapper 负责字符解码。
with ZipFile(zip_path, mode="r") as archive:
with archive.open(member_name, mode="r") as binary_member:
with io.TextIOWrapper(binary_member, encoding=encoding) as text_member:
# 文本层只消费 str,编码错误由调用方按业务策略处理。
return text_member.read()
关闭顺序由嵌套的 with 管理,调用方不必手写多个 close()。外层 ZipFile 关闭后,不应继续使用成员流;官方文档把这种情况定义为 ValueError。这也是把读取逻辑放在上下文块内部的原因。
发布前记住这几个边界
| 场景 | 建议 | 原因 |
|---|---|---|
| 未知内容类型 | 先按 bytes 读取 | 避免错误假设字符编码 |
| 成员名可能重复 | 使用 ZipInfo | 保留具体归档条目 |
| 成员很大 | 循环分块消费 | 控制单次内存占用 |
| 文本成员 | 显式指定编码再解码 | 把数据读取与字符转换分离 |
| 资源生命周期 | 嵌套使用 with | 避免容器或流泄漏 |
相关问题
为什么不直接用 zipfile.Path?
zipfile.Path 更适合把压缩包成员组织成路径式对象;本篇关注的是明确调用 ZipFile.open() 后得到二进制流,并控制读取、解码和关闭边界。两者解决的问题不同。
读取 ZIP 文本时能不能直接得到字符串?
ZipFile.open() 的读取对象是二进制文件式对象。应先读取字节,再使用 io.TextIOWrapper 或 bytes.decode() 按已知编码转换,不能把默认编码当成文件事实。
Python argparse subparsers 怎样组织多命令 CLI
- 上一篇
- Python argparse subparsers 怎样组织多命令 CLI
- 下一篇
- Python concurrent.futures.wait 怎样区分已完成和未完成任务
-
- 文章 · python教程 | 1小时前 | python · Python 进程间通信 multiprocessing shared_memory ShareableList
- Python ShareableList 固定长度共享列表的类型与容量边界
- 163浏览 收藏
-
- 文章 · python教程 | 2小时前 | 工程实践 · Python教程 · Python 对象生命周期 weakref weakref.finalize 清理回调
- Python weakref.finalize 怎样为对象注册清理回调
- 200浏览 收藏
-
- 文章 · python教程 | 2小时前 | python · Python TypeGuard 类型收窄 typing.TypeIs
- Python typing.TypeIs 怎样表达更精确的类型收窄
- 218浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python dataclasses.field 怎样声明不可共享的默认值
- 250浏览 收藏
-
- 文章 · python教程 | 2小时前 | SQLite · Python教程 · Python sqlite3 sqlite3.Row row_factory 按列名读取
- Python sqlite3.Row 怎样按列名读取查询结果
- 197浏览 收藏
-
- 文章 · python教程 | 3小时前 | Python asyncio CancelledError 异步超时 asyncio.timeout TimeoutError
- Python asyncio.timeout 怎样把超时变成可捕获异常
- 419浏览 收藏
-
- 文章 · python教程 | 3小时前 | 消息队列 · python · 异步编程 · Python asyncio Queue.shutdown QueueShutDown
- Python asyncio.Queue.shutdown 怎样让生产者和消费者安全收尾
- 312浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 844次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 844次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 926次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 900次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 730次使用
-
- Python xml.dom.minidom.unlink 怎样释放不再使用的 DOM 树引用
- 2026-10-27 501浏览
-
- Python typing 怎样用 TypeIs 缩小类型
- 2026-10-24 501浏览
-
- Python sqlite3 Connection serialize 怎么导出数据库快照:备份窗口、内存占用与恢复校验
- 2026-08-26 501浏览
-
- Python监控网页状态:requests异常处理实战
- 2026-05-29 501浏览
-
- TensorFlow模型部署为API的TF Serving方法
- 2026-05-26 501浏览

