【发布时间】:2022-12-01 14:36:15
【问题描述】:
我正在像这样使用 python 打开一个 zip 文件...
with open('/home/ubuntu/myzip/myzip.zip', 'rb') as zf:
它按预期工作。内容 zf.read() 被传递给 API。有没有办法修改文件而不改变它的内容?例如在末尾添加一个输入标记。
我需要这样做,以便服务将其视为不同的文件。由于某种原因,它不接受相同的内容。
【问题讨论】:
标签: python
我正在像这样使用 python 打开一个 zip 文件...
with open('/home/ubuntu/myzip/myzip.zip', 'rb') as zf:
它按预期工作。内容 zf.read() 被传递给 API。有没有办法修改文件而不改变它的内容?例如在末尾添加一个输入标记。
我需要这样做,以便服务将其视为不同的文件。由于某种原因,它不接受相同的内容。
【问题讨论】:
标签: python
打开 ZIP 文件进行读写
import zipfile
>>> with zipfile.ZipFile("sample.zip",
mode="r") as archive:
... archive.printdir()
...
File Name
Modified Size
hello.txt
2021-09-07 19:50:10 83
lorem.md
2021-09-07 19:50:10 2609
realpython.md
2021-09-07 19:50:10 428
ZipFile 初始化程序的第一个参数可以是一个字符串,表示您需要打开的 ZIP 文件的路径。此参数也可以接受类文件和类路径对象。在此示例中,您使用基于字符串的路径。
ZipFile 的第二个参数是一个单字母字符串,表示您将用于打开文件的模式。正如您在本节开头了解到的,ZipFile 可以接受四种可能的模式,具体取决于您的需要。 mode 位置参数默认为“r”,所以如果你想以只读方式打开存档,你可以去掉它。
在 with 语句中,您在存档上调用 .printdir() 。 archive 变量现在包含 ZipFile 本身的实例。此函数提供了一种在屏幕上显示底层 ZIP 文件内容的快速方法。该函数的输出具有用户友好的表格格式,其中包含三个信息栏:
文件名 修改的 尺寸 如果你想在尝试打开 ZIP 文件之前确保你的目标是有效的 ZIP 文件,那么你可以将 ZipFile 包装在一个 try … except 语句中并捕获任何 BadZipFile 异常:
>>> import zipfile
>>> try:
... with zipfile.ZipFile("sample.zip") as
archive:
... archive.printdir()
... except zipfile.BadZipFile as error:
... print(error)
...
File Name
Modified Size
hello.txt
2021-09-07 19:50:10 83
lorem.md
2021-09-07 19:50:10 2609
realpython.md
2021-09-07 19:50:10 428
>>> try:
... with
zipfile.ZipFile("bad_sample.zip") as archive:
... archive.printdir()
... except zipfile.BadZipFile as error:
... print(error)
...
File is not a zip file
第一个示例成功打开 sample.zip 而没有引发 BadZipFile 异常。这是因为 sample.zip 具有有效的 ZIP 格式。另一方面,第二个示例无法成功打开 bad_sample.zip,因为该文件不是有效的 ZIP 文件。
要检查有效的 ZIP 文件,您还可以使用 is_zipfile() 函数:
>>> import zipfile
>>> if zipfile.is_zipfile("sample.zip"):
... with zipfile.ZipFile("sample.zip",
"r") as archive:
... archive.printdir()
... else:
... print("File is not a zip file")
...
File Name
Modified Size
hello.txt
2021-09-07 19:50:10 83
lorem.md
2021-09-07 19:50:10 2609
realpython.md
2021-09-07 19:50:10 428
>>> if zipfile.is_zipfile("bad_sample.zip"):
... with
zipfile.ZipFile("bad_sample.zip", "r") as
archive:
... archive.printdir()
... else:
... print("File is not a zip file")
...
File is not a zip file
在这些示例中,您使用带有 is_zipfile() 作为条件的条件语句。此函数采用一个文件名参数,该参数保存文件系统中 ZIP 文件的路径。此参数可以接受字符串、类文件或类路径对象。如果文件名是一个有效的 ZIP 文件,该函数返回 True。否则,它返回 False。
现在假设您想使用 ZipFile 将 hello.txt 添加到 hello.zip 存档中。为此,您可以使用写模式(“w”)。此模式打开一个 ZIP 文件进行写入。如果目标 ZIP 文件存在,则“w”模式会截断它并写入您传入的任何新内容。
注意:如果你对现有文件使用 ZipFile,那么你应该小心使用“w”模式。您可以截断 ZIP 文件并丢失所有原始内容。
如果目标 ZIP 文件不存在,ZipFile 会在您关闭存档时为您创建它:
>>> import zipfile
>>> with zipfile.ZipFile("hello.zip",
mode="w") as archive:
... archive.write("hello.txt")
...
运行此代码后,您的 python-zipfile/ 目录中将有一个 hello.zip 文件。如果您使用 .printdir() 列出文件内容,那么您会注意到 hello.txt 将在那里。在此示例中,您对 ZipFile 对象调用 .write() 。此方法允许您将成员文件写入 ZIP 存档。请注意,.write() 的参数应该是一个现有文件。
注意:ZipFile 足够聪明,可以在您以写入模式使用该类并且目标存档不存在时创建一个新存档。但是,如果这些目录尚不存在,则该类不会在目标 ZIP 文件的路径中创建新目录。
这解释了为什么以下代码不起作用:
>>> import zipfile
>>> with zipfile.ZipFile("missing/hello.zip",
mode="w") as archive:
... archive.write("hello.txt")
...
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or
directory: 'missing/hello.zip'
因为目标 hello.zip 文件路径中的 missing/ 目录不存在,所以会出现 FileNotFoundError 异常。
追加模式(“a”)允许您将新的成员文件追加到现有的 ZIP 文件中。此模式不会截断存档,因此其原始内容是安全的。如果目标 ZIP 文件不存在,则“a”模式会为您创建一个新文件,然后将您作为参数传递给 .write() 的任何输入文件附加。
要尝试“a”模式,请继续将 new_hello.txt 文件添加到新创建的 hello.zip 存档中:
>>> import zipfile
>>> with zipfile.ZipFile("hello.zip",
mode="a") as archive:
... archive.write("new_hello.txt")
...
>>> with zipfile.ZipFile("hello.zip") as
archive:
... archive.printdir()
...
File Name
Modified Size
hello.txt
2021-09-07 19:50:10 83
new_hello.txt
2021-08-31 17:13:44
在这里,您使用追加模式将 new_hello.txt 添加到 hello.zip 文件中。然后运行 .printdir() 以确认新文件存在于 ZIP 文件中。
ZipFile 还支持独占模式(“x”)。此模式允许您专门创建新的 ZIP 文件并将新的成员文件写入其中。当您想要创建一个新的 ZIP 文件而不覆盖现有文件时,您将使用独占模式。如果目标文件已经存在,则会出现 FileExistsError。
最后,如果您使用“w”、“a”或“x”模式创建 ZIP 文件,然后在不添加任何成员文件的情况下关闭存档,则 ZipFile 会创建一个具有适当 ZIP 格式的空存档。
【讨论】: