zipfile.ZipFile()写入必须用'w'或'a'模式,'r'不支持写入;'a'仅对已存在ZIP追加,否则等效'w';需调用close()或with语句;路径须用relpath+arcname转相对路径;中文名需注意编码兼容性;大文件会内存暴涨。
zipfile.ZipFile() 写入模式选错导致压缩包为空
用
创建 ZIP 文件时,
和
模式行为差异很大:选
会清空已有文件并重建;选
才能追加,但若目标不存在,它也会新建——看似一样,实则底层逻辑不同。更关键的是,如果误用
模式打开再写,直接抛
。
写新包一律用
,哪怕只是加一个文件
想往已有 ZIP 里追加?Python 标准库不支持原地追加 ——
只在文件完全不存在时等效于
,存在时才真追加;但一旦 ZIP 已有内容,
会尝试读取目录结构,若损坏或非标准格式就失败
务必调用
或用
语句,否则文件句柄未释放,压缩包可能写入不全、体积为 0
os.walk() 遍历路径传给 write() 时路径错乱
常见错误是把
返回的
+
直接喂给
,结果压缩包里出现完整绝对路径(如
),解压后层层嵌套。ZIP 规范要求内部路径是相对的,
默认保留传入路径的层级。
用
参数重写归档内路径:
计算
推荐用
,其中
是你希望压缩包根目录对应的实际路径
别依赖
拼接 —— 它只取最后一级,丢失中间目录结构
注意 Windows 路径分隔符:传入
时统一用
(ZIP 标准),
内部会处理兼容性
中文文件名乱码或解压失败
ZIP 本身没强制规定编码,Windows 默认用 GBK,macOS/Linux 默认 UTF-8。Python 3 的
在读写时默认按 UTF-8 解析文件名,但老压缩包可能是 GBK 编码,直接
就返回乱码,
则可能抛
。
读取未知来源 ZIP 时,先试
;若报错或内容异常,改用
获取原始
对象,手动 decode:
写入含中文路径的文件,确保源字符串是 Unicode(Python 3 默认),
会自动 UTF-8 编码写入 —— 但 Windows 资源管理器可能不认,需额外兼容
跨平台分发 ZIP?优先用
,它内部对中文更鲁棒;或用第三方库如
显式指定编码
大文件压缩内存暴涨或卡死
默认把整个文件读进内存再压缩,遇到几百 MB 的日志或视频,Python 进程 RSS 瞬间翻倍,还可能触发系统 OOM Killer。这不是 bug,是设计使然 —— 它没流式写入接口。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
立即学习
“
Python免费学习笔记(深入)
”;
小文件(write() 没问题
大文件必须分块读写:用
+ 自己控制
流,但要手算 ZIP 头和校验和,极不推荐
务实方案是绕过
:调用系统命令
,或用
(底层调用系统 zip 或纯 Python 实现,取决于平台)
注意
的
在某些旧版 Python 中不支持
定制,需确认版本 ≥3.7
真正麻烦的不是语法,是 ZIP 规范和操作系统实现之间的缝隙——比如 macOS 的 Archive Utility 对 ZIP64 支持不全,而 Python 默认超过 2GB 就切 ZIP64;又比如有些嵌入式设备解压器只认传统 ZIP,不认数据描述符。这些边界情况,光看文档根本踩不到,得靠实际压一压、解一解才知道。
zipfile.ZipFile()'w''a''w''a''r'ValueError: ZIP does not support writing mode 'r''w''a''w''a'.close()withos.walk()rootfilenameZipFile.write()/home/user/docs/report.txtwrite()arcnamezf.write(full_path, arcname=rel_path)rel_pathos.path.relpath(full_path, start=base_dir)base_diros.path.basename()arcname/zipfilezipfilenamelist()extractall()UnicodeDecodeErrorZipFile.namelist()ZipFile.filelistZipInfoinfo.filename.encode('cp437').decode('gbk')zipfileshutil.make_archive()pyminizipZipFile.write()ZipFile.writestr()zlib.compress()zipfilesubprocess.run(['zip', '-r', 'out.zip', 'dir/'])shutil.make_archive()shutil.make_archive()format='zip'arcname