Python如何不加载全量ZIP文件到内存 实现流式解压与HTTP拉取并行
Python流式下载并并行解压ZIP包实现方案
标准库zipfile默认要求文件对象支持寻址(seek)操作,需要先读取ZIP包尾部的中央目录才能解析文件结构,无法满足不加载全量字节、边下载边解压的需求。我们可以使用专门支持流式ZIP解压的第三方库stream-unzip实现该需求,全程内存占用仅和配置的字节块大小相关,不受压缩包总大小限制。
1. 依赖安装
执行以下命令安装需要的依赖:
pip install stream-unzip httpx
其中httpx用于发起流式HTTP请求,也可以替换为支持流式响应的其他HTTP客户端。
2. 同步实现代码
from stream_unzip import stream_unzip import httpx def stream_unzip_from_url(url, chunk_size=65536): # 发起流式GET请求,不预加载全量响应内容 with httpx.stream("GET", url) as resp: # 校验请求状态 resp.raise_for_status() # 直接将下载的字节流喂给流式解压工具 for file_name, file_size, file_chunks in stream_unzip(resp.iter_bytes(chunk_size=chunk_size)): # 解码文件名(根据实际编码调整,默认utf-8) file_name_str = file_name.decode("utf-8") print(f"处理文件:{file_name_str}") # 逐块写入本地文件,无需加载整个文件到内存 with open(file_name_str, "wb") as f: for chunk in file_chunks: f.write(chunk) if __name__ == "__main__": # 替换为实际的ZIP包下载地址 target_url = "https://example.com/large_file.zip" stream_unzip_from_url(target_url)
3. 异步实现代码
如果需要使用异步IO进一步提升性能,可以使用异步版本的实现:
import asyncio from stream_unzip import async_stream_unzip import httpx async def async_stream_unzip_from_url(url, chunk_size=65536): async with httpx.AsyncClient() as client: async with client.stream("GET", url) as resp: resp.raise_for_status() # 异步迭代下载的字节流 async for file_name, file_size, file_chunks in async_stream_unzip(resp.aiter_bytes(chunk_size=chunk_size)): file_name_str = file_name.decode("utf-8") print(f"处理文件:{file_name_str}") with open(file_name_str, "wb") as f: async for chunk in file_chunks: f.write(chunk) if __name__ == "__main__": target_url = "https://example.com/large_file.zip" asyncio.run(async_stream_unzip_from_url(target_url))
注意事项
- 流式解压支持绝大多数标准ZIP格式,包括带数据描述符的ZIP包、加密ZIP包(加密包需给
stream_unzip传入password参数),不支持特殊分卷ZIP等非标准格式。 - 可根据实际内存情况调整
chunk_size参数,默认64KB是兼顾性能和内存占用的通用配置。 - 如果需要过滤压缩包内的指定文件,无需解压全部内容,在迭代到对应文件时直接跳过处理即可。
内容的提问来源于stack exchange,提问作者Michal Charemza
相关产品推荐
相关产品推荐

