Python的zipfile模块无法更新条目
我想用Python的zipfile模块来更新一个压缩文件里的内容。我的问题是,这样做会生成一个新的条目。
假设我有以下这段代码:
from zipfile import ZipFile,ZIP_DEFLATED
with ZipFile("myfile.zip","w") as z:
z.writestr("hello.txt", "the content of hello.txt", ZIP_DEFLATED)
### how to update the hello.txt file here ?
z.writestr("hello.txt", "the content of hello.txt", ZIP_DEFLATED)
执行完这段代码后,压缩文件里会有两个条目,而不是一个:
$ unzip -l myfile.zip
Archive: myfile.zip
Length Date Time Name
--------- ---------- ----- ----
24 2013-02-19 22:48 hello.txt
24 2013-02-19 22:48 hello.txt
--------- -------
48 2 files
$ python --version
Python 3.3.0
$
我知道可以写一个全新的文件,但如果内容很大,这样做会花费很多时间。
其实,zip(1)这个工具可以做到这一点(使用“-u”选项),那为什么Python做不到呢?有没有办法用Python实现这个功能呢?
2 个回答
0
我觉得 zipfile
这个模块可能无法像你想的那样修改压缩文件。如果可以的话,它应该会有一个可以从 ZipFile
中删除文件的方法,但实际上并没有这个方法。
6
zip格式没有简单的方法来删除或替换压缩包里的文件。可能有一些库可以做到这一点,但我不知道具体有哪些。
不过等等:
zip(1)工具可以做到这一点(使用“-u”选项),那为什么Python不能呢?
其实,-u
的作用只是告诉它“只有在文件时间戳不更新的情况下才替换已有文件”,这在这里并不重要。如果不加-u
,默认命令是add
,它会做同样的事情,但不检查时间戳:
更新已有的条目并添加新文件。如果压缩包不存在,就创建一个。这是默认模式。
更重要的是,正如你提到的手册页明确指出:
Zip文件。当修改一个已有的zip压缩包时,zip会先写一个临时文件,里面是新内容,只有在新版本创建完成且没有错误时,才会替换掉旧的文件。
这正是你想做的:先把完整的新文件写到一个临时位置,然后再用新文件替换掉原来的文件。
如果你需要在Windows上实现,这可能会有点麻烦。(如果不需要,就直接使用tempfile.NamedTemporaryFile
和os.rename
。)但你已经知道怎么做了:
我知道如何写一个完整的新文件,但如果内容很大,这会花很多时间。
其实这和zip -u
花的时间差不多。