Python的zipfile模块无法更新条目。

4

我希望使用Python的zipfile模块更新.zip文件中的一条记录。

我的问题是,这会生成一个新条目。

请假设我有以下代码:

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)

之后,实际的zip文件有两个条目而不是一个:

$ 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个回答

6
“zip”格式没有简单的方法来删除或替换存档中的文件。可能有一些库可以原地进行操作,但我不知道有哪个库可以这样做。
但是,请等待:
引用块中提到:“zip(1)实用程序可以执行此操作(使用“-u”选项),那么为什么Python不能呢?”
首先,“-u”所做的就是告诉它“仅在时间戳不更新时才替换现有文件”,这在这里并不真正相关。如果没有“-u”,则默认命令是“add”,它会执行相同的操作而不检查时间戳:
更新现有条目并添加新文件。如果存档不存在,则创建它。这是默认模式。
但更重要的是,正如您所引用的手册明确指出的那样:
Zip文件。当更改现有的zip存档时,zip将使用新内容编写一个临时文件,并仅在创建新版本的过程完成且没有错误时才替换旧文件。

这正是您想要做的:将完整的新文件写入临时位置,然后用新文件替换原始文件。

如果需要在Windows上运行,则可能会有些麻烦。(如果不需要,请使用tempfile.NamedTemporaryFileos.rename。)但是您已经知道如何操作:

我知道编写完整的新文件的方法,但如果内容很大,这将花费很多时间。

zip -u所需的时间一样多。


非常好的答案,谢谢。我希望zip(1)修改文件而不是创建一个新文件。因此,如果甚至zip也没有提供修改文件的方法,那么Python也不会提供。 - dnagy
2
@dnagy:很少有Unix风格的工具会直接修改文件。即使这样做并不简单,但总是更安全的方法是先写入临时文件,然后重命名。这样,如果出现错误,您仍然拥有原始文件,而不是一个被截断或无法恢复的垃圾文件。 - abarnert

0

我怀疑zipfile模块能够像你想要的那样修改存档文件。如果可以的话,就会有一种方法从ZipFile中删除文件,但实际上并没有。


这对我来说更像是一个错误。如果我使用命令行 zip(1) 工具,我永远无法在归档中获得两次相同的条目。 - dnagy
你认为这是一个需要的API,还是他们只是尚未实现这些方法? - dnagy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接