You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 04:55:18