Skip to main content

13.5. zipfile —使用ZIP存档

源代码: Lib/zipfile.py


ZIP文件格式是常见的归档和压缩标准。此模块提供了创建,读取,写入,附加和列出ZIP文件的工具。此模块的任何高级使用都需要了解 PKZIP Application Note 中定义的格式。

此模块当前不处理多磁盘ZIP文件。它可以处理使用ZIP64扩展名(即大小超过4 GiB的ZIP文件)的ZIP文件。它支持在ZIP存档中加密文件的解密,但它目前不能创建加密文件。解密非常慢,因为它是在本机Python而不是C中实现的。

模块定义以下项目:

exception zipfile.BadZipFile

错误ZIP文件引发的错误。

3.2 新版功能.

exception zipfile.BadZipfile

BadZipFile 的别名,与旧版本的Python兼容。

3.2 版后已移除.

exception zipfile.LargeZipFile

ZIP文件需要ZIP64功能但尚未启用时引发的错误。

class zipfile.ZipFile

用于读取和写入ZIP文件的类。有关构造函数的详细信息,请参见 ZipFile对象 部分。

class zipfile.PyZipFile

用于创建包含Python库的ZIP存档的类。

class zipfile.ZipInfo(filename='NoName', date_time=(1980, 1, 1, 0, 0, 0))

用于表示有关归档成员的信息的类。此类的实例由 ZipFile 对象的 getinfo()infolist() 方法返回。 zipfile 模块的大多数用户不需要创建这些模块,而只使用由此模块创建的模块。 filename 应该是归档成员的全名,date_time 应该是一个包含六个字段的元组,这六个字段描述文件最后一次修改的时间;字段在 ZipInfo对象 部分中描述。

zipfile.is_zipfile(filename)

如果 filename 是基于其幻数的有效ZIP文件,则返回 True,否则返回 Falsefilename 也可以是文件或类似文件的对象。

在 3.1 版更改: 支持文件和类文件对象。

zipfile.ZIP_STORED

未压缩的归档成员的数字常量。

zipfile.ZIP_DEFLATED

常用ZIP压缩方法的数字常量。这需要 zlib 模块。

zipfile.ZIP_BZIP2

BZIP2压缩方法的数字常量。这需要 bz2 模块。

3.3 新版功能.

zipfile.ZIP_LZMA

LZMA压缩方法的数字常量。这需要 lzma 模块。

3.3 新版功能.

注解

ZIP文件格式规范包括自2001年以来对bzip2压缩的支持以及自2006年以来的LZMA压缩。然而,一些工具(包括旧的Python版本)不支持这些压缩方法,并且可能拒绝完全处理ZIP文件,无法提取单个文件。

参见

PKZIP Application Note

关于ZIP文件格式的文档由Phil Katz,使用的格式和算法的创建者。

Info-ZIP主页

有关Info-ZIP项目的ZIP归档程序和开发库的信息。

13.5.1. ZipFile对象

class zipfile.ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True)

打开ZIP文件,其中 file 可以是文件(字符串)或类文件对象的路径。 mode 参数应该是 'r' 来读取现有文件,'w' 来截断和写入新文件,'a' 来附加到现有文件,或者 'x' 来专门创建和写入新文件。如果 mode'x'file 是指现有文件,则会引发 FileExistsError。如果 mode'a'file 引用现有的ZIP文件,则会向其中添加其他文件。如果 file 不引用ZIP文件,则会将新的ZIP存档附加到文件。这是为了将ZIP归档添加到另一个文件(如 python.exe)。如果 mode'a',并且文件根本不存在,则创建它。如果 mode'r''a',则文件应该是可搜索的。 compression 是ZIP压缩方法,用于写入归档时,应该是 ZIP_STOREDZIP_DEFLATEDZIP_BZIP2ZIP_LZMA;无法识别的值将导致 NotImplementedError 升高。如果指定了 ZIP_DEFLATEDZIP_BZIP2ZIP_LZMA,但是相应的模块(zlibbz2lzma)不可用,则提高 RuntimeError。默认值为 ZIP_STORED。如果 allowZip64True (默认),当zip文件大于2 GiB时,zipfile将创建使用ZIP64扩展名的ZIP文件。如果是假 zipfile 将引发异常时,ZIP文件将需要ZIP64扩展。

如果使用模式 'w''x''a' 以及 closed 创建文件,而不向归档中添加任何文件,则空归档的相应ZIP结构将被写入该文件。

ZipFile也是一个上下文管理器,因此支持 with 语句。在示例中,myzipwith 语句的套件完成后关闭 - 即使发生异常:

with ZipFile('spam.zip', 'w') as myzip:
    myzip.write('eggs.txt')

3.2 新版功能: 添加了使用 ZipFile 作为上下文管理器的能力。

在 3.3 版更改: 增加了对 bzip2lzma 压缩的支持。

在 3.4 版更改: 默认情况下启用ZIP64扩展。

在 3.5 版更改: 增加了对写入不可搜索流的支持。添加了对 'x' 模式的支持。

在 3.6 版更改: 以前,为无法识别的压缩值引发了一个简单的 RuntimeError

ZipFile.close()

关闭归档文件。您必须在退出程序之前调用 close(),否则不会写入基本记录。

ZipFile.getinfo(name)

返回具有关于存档成员 name 的信息的 ZipInfo 对象。为 getinfo() 调用当前未包含在归档中的名称将产生 KeyError

ZipFile.infolist()

返回包含归档的每个成员的 ZipInfo 对象的列表。如果打开了现有归档,则对象与磁盘上实际ZIP文件中的条目的顺序相同。

ZipFile.namelist()

按名称返回归档成员的列表。

ZipFile.open(name, mode='r', pwd=None, *, force_zip64=False)

作为二进制文件状对象访问归档的成员。 name 可以是归档中的文件的名称或 ZipInfo 对象。 mode 参数(如果包含)必须是 'r' (默认值)或 'w'pwd 是用于解密加密ZIP文件的密码。

open() 也是一个上下文管理器,因此支持 with 语句:

with ZipFile('spam.zip') as myzip:
    with myzip.open('eggs.txt') as myfile:
        print(myfile.read())

使用 mode 'r',文件状对象(ZipExtFile)是只读的,并提供以下方法:read()readline()readlines()__iter__()__next__()。这些对象可以独立于ZipFile操作。

使用 mode='w',返回可写的文件句柄,它支持 write() 方法。当可写文件句柄打开时,尝试读取或写入ZIP文件中的其他文件将引发 ValueError

在写入文件时,如果文件大小不是预先知道的,但可能超过2 GiB,则传递 force_zip64=True 以确保头文件格式能够支持大文件。如果文件大小是预先已知的,则构造具有 file_size 集合的 ZipInfo 对象,并将其用作 name 参数。

注解

open()read()extract() 方法可以获取文件名或 ZipInfo 对象。当您尝试读取包含重复名称的成员的ZIP文件时,您将会感激此。

在 3.6 版更改: 删除了 mode='U' 的支持。在 universal newlines 模式下使用 io.TextIOWrapper 读取压缩文本文件。

在 3.6 版更改: open() 现在可以用于使用 mode='w' 选项将文件写入归档。

在 3.6 版更改: 在封闭的ZipFile上调用 open() 将产生 ValueError。以前,RuntimeError 被提出。

ZipFile.extract(member, path=None, pwd=None)

将成员从归档提取到当前工作目录; member 必须是其全名或 ZipInfo 对象。其文件信息尽可能精确地提取。 path 指定要提取到的不同目录。 member 可以是文件名或 ZipInfo 对象。 pwd 是用于加密文件的密码。

返回已创建的标准化路径(目录或新文件)。

注解

如果成员文件名是绝对路径,则驱动器/UNC共享点和前导(后)斜杠将被删除,例如:///foo/bar 在Unix上变为 foo/bar,在Windows上 C:\foo\bar 变为 foo\bar。并且将删除成员文件名中的所有 ".." 组件,例如:../../foo../../ba..r 变为 foo../ba..r。在Windows上用下划线(_)替换的非法字符(:<>|"?*)。

在 3.6 版更改: 在封闭的ZipFile上调用 extract() 将产生 ValueError。以前,RuntimeError 被提出。

ZipFile.extractall(path=None, members=None, pwd=None)

将归档中的所有成员解压缩到当前工作目录。 path 指定要提取到的不同目录。 members 是可选的,并且必须是 namelist() 返回的列表的子集。 pwd 是用于加密文件的密码。

警告

切勿在未经预先检查的情况下从不受信任的来源中提取存档。有可能在 path 之外创建文件,例如。具有以 "/" 开头的绝对文件名或具有两个点 ".." 的文件名的成员。此模块尝试阻止。见 extract() 说明。

在 3.6 版更改: 在封闭的ZipFile上调用 extractall() 将产生 ValueError。以前,RuntimeError 被提出。

ZipFile.printdir()

将归档的目录打印到 sys.stdout

ZipFile.setpassword(pwd)

pwd 设置为默认密码以提取加密文件。

ZipFile.read(name, pwd=None)

返回归档中文件 name 的字节。 name 是归档中文件的名称,或 ZipInfo 对象。归档必须打开以进行读取或追加。 pwd 是用于加密文件的密码,如果指定,它将覆盖使用 setpassword() 设置的默认密码。在使用除 ZIP_STOREDZIP_DEFLATEDZIP_BZIP2ZIP_LZMA 之外的压缩方法的ZipFile上调用 read() 将产生 NotImplementedError。如果相应的压缩模块不可用,也会出现错误。

在 3.6 版更改: 在封闭的ZipFile上调用 read() 将产生 ValueError。以前,RuntimeError 被提出。

ZipFile.testzip()

读取归档中的所有文件,并检查其CRC和文件头。返回第一个坏文件的名称,否则返回 None

在 3.6 版更改: 在封闭的ZipFile上调用 testfile() 将产生 ValueError。以前,RuntimeError 被提出。

ZipFile.write(filename, arcname=None, compress_type=None)

将名为 filename 的文件写入归档,给它归档名称 arcname (默认情况下,这将与 filename 相同,但没有驱动器号和删除前导路径分隔符)。如果给定,compress_type 将为新条目的构造函数覆盖为 compression 参数指定的值。归档必须以模式 'w''x''a' 打开。

注解

ZIP文件没有正式的文件名编码。如果您有unicode文件名,您必须在将它们传递给 write() 之前将它们转换为所需编码中的字节字符串。 WinZip将所有文件名解释为在CP437中编码的,也称为DOS拉丁文。

注解

归档名称应该相对于归档根目录,也就是说,它们不应以路径分隔符开头。

注解

如果 arcname (或 filename,如果未给出 arcname)包含空字节,则归档中的文件名将在空字节处截断。

在 3.6 版更改: 在用模式 'r' 或关闭的ZipFile创建的ZipFile上调用 write() 将产生 ValueError。以前,提出了 RuntimeError

ZipFile.writestr(zinfo_or_arcname, data[, compress_type])

将字符串 data 写入归档; zinfo_or_arcname 是它将在归档中给出的文件名,或 ZipInfo 实例。如果它是一个实例,至少必须给出文件名,日期和时间。如果是名称,则日期和时间设置为当前日期和时间。必须使用模式 'w''x''a' 打开归档。

如果给定,compress_type 将为新条目的构造函数或 zinfo_or_arcname (如果是 ZipInfo 实例)覆盖为 compression 参数指定的值。

注解

当将 ZipInfo 实例作为 zinfo_or_arcname 参数传递时,所使用的压缩方法将是在给定 ZipInfo 实例的 compress_type 成员中指定的。默认情况下,ZipInfo 构造函数将此成员设置为 ZIP_STORED

在 3.2 版更改: compress_type 参数。

在 3.6 版更改: 在用模式 'r' 或关闭的ZipFile创建的ZipFile上调用 writestr() 将产生 ValueError。以前,提出了 RuntimeError

还提供以下数据属性:

ZipFile.debug

要使用的调试输出的级别。这可以从 0 (默认,无输出)设置为 3 (最多输出)。调试信息写入 sys.stdout

ZipFile.comment

与ZIP文件相关联的注释文本。如果为使用模式 'w''x''a' 创建的 ZipFile 实例分配注释,则该值应为不超过65535字节的字符串。当调用 close() 时,长于此值的注释将在写入的归档中被截断。

13.5.2. PyZipFile对象

PyZipFile 构造函数采用与 ZipFile 构造函数相同的参数,以及一个附加参数 optimize

class zipfile.PyZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True, optimize=-1)

3.2 新版功能: optimize 参数。

在 3.4 版更改: 默认情况下启用ZIP64扩展。

实例除了 ZipFile 对象的方法之外还有一个方法:

writepy(pathname, basename='', filterfunc=None)

搜索文件 *.py 并将相应的文件添加到归档中。

如果未给出 PyZipFileoptimize 参数或 -1,则相应的文件是 *.pyc 文件,如果必要,则进行编译。

如果 PyZipFileoptimize 参数是 012,则仅将具有该优化级别的文件(请参阅 compile())添加到归档中,如有必要,则进行编译。

如果 pathname 是文件,则文件名必须以 .py 结尾,并且只有(对应的 *.py[co])文件在顶层添加(无路径信息)。如果 pathname 是不以 .py 结尾的文件,则将引发 RuntimeError。如果它是一个目录,并且该目录不是包目录,则所有文件 *.py[co] 在顶级被添加。如果目录是包目录,则所有 *.py[co] 都以包名称作为文件路径添加,并且如果任何子目录是包目录,则所有这些都递归地添加。

basename 仅供内部使用。

filterfunc,如果给定,必须是一个函数接受单个字符串参数。它将在添加到归档文件之前传递每个路径(包括每个单独的完整文件路径)。如果 filterfunc 返回false值,则不会添加路径,如果它是目录,则其内容将被忽略。例如,如果我们的测试文件都在 test 目录中或以字符串 test_ 开头,我们可以使用 filterfunc 来排除它们:

>>> zf = PyZipFile('myprog.zip')
>>> def notests(s):
...     fn = os.path.basename(s)
...     return (not (fn == 'test' or fn.startswith('test_')))
>>> zf.writepy('myprog', filterfunc=notests)

writepy() 方法使档案具有这样的文件名:

string.pyc                   # Top level name
test/__init__.pyc            # Package directory
test/testall.pyc             # Module test.testall
test/bogus/__init__.pyc      # Subpackage directory
test/bogus/myfile.pyc        # Submodule test.bogus.myfile

3.4 新版功能: filterfunc 参数。

13.5.3. ZipInfo对象

ZipInfo 类的实例由 ZipFile 对象的 getinfo()infolist() 方法返回。每个对象存储有关ZIP存档的单个成员的信息。

有一个类方法为文件系统文件创建 ZipInfo 实例:

classmethod ZipInfo.from_file(filename, arcname=None)

为文件系统上的文件构建 ZipInfo 实例,以准备将其添加到zip文件。

filename 应该是文件系统上的文件或目录的路径。

如果指定了 arcname,它将用作归档中的名称。如果未指定 arcname,则名称将与 filename 相同,但删除了任何驱动器盘符和前导路径分隔符。

3.6 新版功能.

实例具有以下方法和属性:

ZipInfo.is_dir()

如果此存档成员是目录,则返回 True

这使用条目的名称:目录应始终以 / 结束。

3.6 新版功能.

ZipInfo.filename

归档中的文件的名称。

ZipInfo.date_time

上次修改归档成员的时间和日期。这是一个包含六个值的元组:

指数

0

年(> = 1980)

1

月(从1个月)

2

日(月份)

3

小时(从零开始)

4

分钟(从零开始)

5

秒(从零开始)

注解

ZIP文件格式不支持1980之前的时间戳。

ZipInfo.compress_type

归档成员的压缩类型。

ZipInfo.comment

个人档案成员的注释。

ZipInfo.extra

扩展字段数据。 PKZIP Application Note 包含对此字符串中包含的数据的内部结构的一些意见。

ZipInfo.create_system

创建ZIP存档的系统。

ZipInfo.create_version

PKZIP版本创建ZIP存档。

ZipInfo.extract_version

PKZIP版本需要提取归档。

ZipInfo.reserved

必须为零。

ZipInfo.flag_bits

ZIP标志位。

ZipInfo.volume

文件头的卷编号。

ZipInfo.internal_attr

内部属性。

ZipInfo.external_attr

外部文件属性。

ZipInfo.header_offset

字节偏移到文件头。

ZipInfo.CRC

CRC-32的未压缩文件。

ZipInfo.compress_size

压缩数据的大小。

ZipInfo.file_size

未压缩文件的大小。

13.5.4. 命令行界面

zipfile 模块提供了一个简单的命令行界面来与ZIP压缩文件交互。

如果要创建新的ZIP存档,请在 -c 选项后指定其名称,然后列出应包括的文件名:

$ python -m zipfile -c monty.zip spam.txt eggs.txt

传递目录也是可以接受的:

$ python -m zipfile -c monty.zip life-of-brian_1979/

如果要将ZIP存档提取到指定的目录中,请使用 -e 选项:

$ python -m zipfile -e monty.zip target-dir/

有关ZIP存档中文件的列表,请使用 -l 选项:

$ python -m zipfile -l monty.zip

13.5.4.1. 命令行选项

-l <zipfile>

列出zip文件中的文件。

-c <zipfile> <source1> ... <sourceN>

从源文件创建zip文件。

-e <zipfile> <output_dir>

将zip文件解压缩到目标目录中。

-t <zipfile>

测试zip文件是否有效。