Python如何向zip/tar压缩包追加文件且不丢失原有文件
问题根因
调用zipfile.write()后原有文件消失,核心原因是打开压缩包时使用了'w'写入模式:该模式和Python内置open()的'w'模式逻辑完全一致,会直接清空目标文件的所有原有内容,从头创建新的空压缩包,自然之前的旧文件都没了。
ZIP格式追加文件实现
要给已有ZIP包追加文件且保留原有内容,打开时必须使用'a'(追加)模式。
import zipfile import os zip_file_path = "test.zip" # 替换成你的现有zip包路径 new_file_path = "new_file.txt" # 替换成要添加的本地文件路径 save_name_in_zip = os.path.basename(new_file_path) # 压缩包内存储的文件名 with zipfile.ZipFile( zip_file_path, mode="a", # 核心:用追加模式,不会清空原有内容 compression=zipfile.ZIP_DEFLATED, # 启用压缩,默认是不压缩的ZIP_STORED compresslevel=5 ) as zf: # 可选:检查是否有同名文件,避免包内出现重复条目 if save_name_in_zip not in zf.namelist(): zf.write(new_file_path, arcname=save_name_in_zip)
注意:ZIP格式本身的结构限制,'a'模式不会覆盖包内已有的同名文件,只会新增一条同名记录,解压时后写入的文件会覆盖先写入的。如果需要替换包内已有同名文件,不能直接用追加模式,需要先把原有压缩包的所有文件读取到临时目录/内存,剔除要替换的旧条目后加入新文件,再重新打包成ZIP覆盖原文件。
TAR格式追加文件实现
TAR格式分两种情况处理:
未压缩的普通.tar包
直接用'a'模式打开即可追加,逻辑和ZIP追加一致:
import tarfile import os tar_file_path = "test.tar" new_file_path = "new_file.txt" save_name_in_tar = os.path.basename(new_file_path) with tarfile.open(tar_file_path, mode="a") as tf: if save_name_in_tar not in tf.getnames(): tf.add(new_file_path, arcname=save_name_in_tar)
带压缩的.tar.gz/.tar.bz2/.tar.xz包
这类压缩后的TAR包不支持直接流式追加,强行用'a'模式打开会损坏文件结构,必须通过临时文件中转,重写整个压缩包:
import tarfile import os import tempfile tar_gz_path = "test.tar.gz" new_file_path = "new_file.txt" save_name_in_tar = os.path.basename(new_file_path) # 创建临时文件存新的压缩包 with tempfile.NamedTemporaryFile(delete=False, suffix=".tar.gz") as tmp_fp: tmp_file_path = tmp_fp.name try: # 读取原有压缩包内容 with tarfile.open(tar_gz_path, mode="r:gz") as src_tf: # 写入新压缩包 with tarfile.open(tmp_file_path, mode="w:gz") as dst_tf: # 先拷贝所有原有文件,跳过要替换的同名旧文件 for member in src_tf.getmembers(): if member.name == save_name_in_tar: continue file_obj = src_tf.extractfile(member) if file_obj: dst_tf.addfile(member, file_obj) # 追加新文件 dst_tf.add(new_file_path, arcname=save_name_in_tar) # 用新包替换原文件 os.replace(tmp_file_path, tar_gz_path) finally: # 清理临时文件 if os.path.exists(tmp_file_path): os.unlink(tmp_file_path)
常见踩坑点
- 只要打开压缩包时传了
'w'模式,不管包内之前有什么内容,都会被直接清空,这是绝大多数人丢文件的直接原因 - ZIP格式原生不支持直接删除、修改包内已有的文件条目,所有涉及修改现有条目的操作都需要全量重写压缩包
- 带压缩的TAR包不要尝试直接用追加模式打开,必然会损坏压缩包结构,必须走重写流程
内容的提问来源于stack exchange,提问作者Akshat
相关产品推荐
相关产品推荐

