用 zipfile.ZipFile 打包时需显式设置 arcname 避免冗余路径,解压必须用 extractall(path=...) 并校验路径安全性,大文件慎用内存式 write(),中文名需适配目标环境编码。

用 zipfile.ZipFile 打包指定文件时,路径处理最容易出错
直接传入相对路径或绝对路径给 write(),解压后可能多出冗余父目录(比如整个 /home/user/project/src/ 都被包进去),或者报 FileNotFoundError。根本原因是 write() 的第二个参数 arcname 控制归档内路径,不设就默认用原始路径全量保留。
- 想打包
./logs/app.log且解压后只出现app.log:调用zf.write('./logs/app.log', arcname='app.log') - 批量加多个文件时,建议用
os.path.basename(filepath)提取文件名作为arcname,避免手动切字符串出错 - 别用
os.chdir()切工作目录来“绕过”路径问题——临时改 cwd 容易污染后续逻辑,且多线程下不安全
解压到指定目录必须用 extractall(path=...),不能只靠 os.chdir()
zipfile.ZipFile.extractall() 默认解到当前工作目录,但很多人误以为先 os.chdir('/target') 再 extractall() 就能控制位置,其实不行:部分 ZIP 文件里路径是绝对的(如 /etc/config.txt),或含 ../,会导致写到意外位置甚至覆盖系统文件。
- 始终显式传
path参数:zf.extractall(path='/tmp/unzipped') - 解压前先用
zf.namelist()检查是否有危险路径(含../或以/开头),有则拒绝解压或预处理arcname - Windows 下注意
path用正斜杠或双反斜杠,单反斜杠会被 Python 当转义符('C:\output'错,r'C:\output'或'C:/output'对)
ZIP_DEFLATED 是默认压缩方式,但大文件慎用 write() 全内存操作
zipfile 默认用 ZIP_DEFLATED,压缩率高,但所有写入都走内存缓冲——如果一次 write() 一个 500MB 的日志文件,Python 进程内存会瞬间涨 500MB+,还可能触发 OOM。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 对单个大文件,改用分块流式写入:先
zf.writestr()写小段,或更稳妥地用外部命令(如subprocess.run(['zip', '-q', 'out.zip', 'bigfile.bin'])) - 确认是否真需要压缩:纯打包可设
compression=zipfile.ZIP_STORED,速度极快且零内存膨胀 -
ZipFile构造时的mode参数影响行为:'w'覆盖,'a'追加(但追加不支持随机删已有项)
中文文件名乱码?不是编码问题,是 ZIP 标准本身没统一规定
Python 3.7+ 默认用 UTF-8 存文件名,但老系统(如 Windows 自带解压工具、某些嵌入式设备)只认 CP437 或 GBK。这不是你代码写错了,而是 ZIP 规范留的坑。
立即学习“Python免费学习笔记(深入)”;
- 若目标环境固定(如只给 Windows 用户),可用
zipfile.ZipInfo手动设filename字节序列:info = zipfile.ZipInfo(filename.encode('gbk')),再zf.writestr(info, content) - 更通用的做法:放弃中文文件名,用英文+下划线命名,或在压缩包内放一个
README.txt说明映射关系 - 别信网上“改源码加
setencoding”的方案——那是针对旧版 Python 的 hack,新版已移除该接口

















