zipfile模块可不解压直接读取ZIP内文件:用ZipFile.open()获取bytes流,再按实际编码解码;文本需decode(注意GBK/UTF-8等编码差异),二进制文件应直接处理bytes并用BytesIO适配seek需求,加密ZIP不支持读取。

可以,zipfile 模块原生支持不解压直接读取 ZIP 内文件内容,但必须注意编码、路径和文件类型限制。
怎么用 zipfile.ZipFile 打开并读取 ZIP 内的文本文件
核心是用 ZipFile.open() 获取类似文件对象的流,再按需解码。不能直接用 read() 返回字符串,它返回的是 bytes。
常见错误:直接对 open() 返回的对象调用 .decode('utf-8') 而不检查实际编码——ZIP 文件内文件名和内容编码可能不一致,尤其 Windows 打包的 ZIP 常含 GBK 编码文本。
- 先用
ZipFile.namelist()查看有哪些文件,确认目标路径是否准确(注意路径分隔符是/,不是\) - 用
with ZipFile('a.zip') as z:确保自动关闭 - 用
z.open('data.txt').read()得到bytes,再根据已知编码解码;若不确定,可试chardet.detect()或用errors='replace'容错
with zipfile.ZipFile('archive.zip') as z:
with z.open('config.json') as f:
content = f.read().decode('utf-8')
data = json.loads(content)读取 ZIP 中的二进制文件(如图片、PDF)要特别注意什么
二进制文件不能 decode,也不能用 TextIOWrapper 包装。直接读取 bytes 后按需处理即可,比如传给 PIL.Image.open() 或写入磁盘。
立即学习“Python免费学习笔记(深入)”;
容易踩的坑:z.open() 返回的对象不支持 seek()(除非 ZIP 是“流式”格式且未加密),所以像 Image.open() 这类依赖随机读取的库可能失败。
- 安全做法:先
f.read()全部载入内存,再用io.BytesIO()构造可 seek 的流 - 加密 ZIP 不支持直接读取,会抛
RuntimeError: File 'xxx' is encrypted - ZIP64 格式、跨卷 ZIP、损坏 ZIP 都会导致
BadZipFile异常
from io import BytesIO
from PIL import Image
<p>with zipfile.ZipFile('images.zip') as z:
with z.open('photo.jpg') as f:
img_data = f.read() # bytes
img = Image.open(BytesIO(img_data))
zipfile.Path(Python 3.12+)比传统方式好在哪
zipfile.Path 提供了类似 pathlib.Path 的接口,让遍历、判断类型、读取更自然,尤其适合嵌套目录结构的 ZIP。
但它不改变底层行为:依然不支持写入、不支持加密 ZIP、不支持 ZIP64 的某些扩展。而且 Python 3.12 以下版本不可用,老项目慎用。
-
Path(zf).joinpath('sub/').iterdir()可以像文件系统一样遍历子项 -
Path(zf, 'data.csv').read_text(encoding='utf-8')自动处理解码 - 仍需手动处理编码错误,
read_text()默认用locale.getpreferredencoding(),不一定可靠
import zipfile
from zipfile import Path
<p>with zipfile.ZipFile('report.zip') as zf:
root = Path(zf)
for p in root.joinpath('tables/').iterdir():
if p.name.endswith('.csv'):
print(p.read_text(encoding='gbk')) # 注意此处显式指定编码真正麻烦的不是“能不能读”,而是 ZIP 内部文件名编码混乱、内容编码未知、以及某些第三方工具生成的非标 ZIP(比如带空字节、非法 UTF-8 字节序列)。遇到读取出错,优先检查 zf.filelist[0].filename 的原始字节值,而不是盲目猜编码。


















