# 13.5. `zipfile` — ZIP 归档访问

源代码： Lib / zipfile.py

ZIP文件格式是一种常见的归档和压缩标准.本模块提供了工具来创建、 读、 写、 追加，列出一个 ZIP 文件。此模块的任何高级使用将需要了解如PKZIP应用笔记中定义的格式。

本模块不能目前处理多磁盘 ZIP 文件。它可以处理 ZIP 文件，使用 ZIP64 扩展 （也就是那些在大小超过 4 GiB 的 ZIP 文件）。它支持加密ZIP 存档文件的解密，但它当前不能创建加密的文件。解密是极其缓慢的当它在本机 Python，而不是 C.中实现.

模块定义以下项目：

exception `zipfile.``BadZipFile`

  错误ZIP文件引发的错误。

  版本3.2中的新功能。

exception `zipfile.``BadZipfile`

  为了与旧的Python版本兼容，`BadZipFile`的别名。

  自3.2版起已弃用。

exception `zipfile.``LargeZipFile`

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

class `zipfile.` `ZipFile`

  用于读取和写入ZIP文件的类。有关构造函数的详细信息，请参见ZipFile Objects一节。

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 Objects部分中描述。

`zipfile.``is_zipfile`(filename)

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

  在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应用笔记
  关于ZIP文件格式的文档由Phil Katz，使用的格式和算法的创建者。
Info-ZIP主页
  有关Info-ZIP项目的ZIP归档程序和开发库的信息。

## 13.5.1. ZipFile Objects

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

  打开ZIP文件，其中文件可以是文件（字符串）或类似文件的对象的路径。模式参数应为`'r'`以读取现有文件`'w'`以截断并写入新文件`'a'`以附加到现有文件，或`'x'`以专门创建和写入新文件。如果模式为`'x'`且file变量指现有文件，则会引发`FileExistsError`。如果模式是`'a'`和文件指现有的ZIP文件，则会向其添加其他文件。如果文件不引用ZIP文件，则会将新的ZIP存档附加到该文件。这是为了将ZIP存档添加到另一个文件（例如`python.exe`）。如果模式是`a`，且文件根本不存在，则会创建该文件。如果模式为`r`或`a`，则文件应为可搜索的。压缩是在撰写封存时使用的ZIP压缩方法，应为`ZIP_STORED`，`ZIP_DEFLATED`，`ZIP_BZIP2` `ZIP_LZMA`；无法识别的值将引起`RuntimeError`。If `ZIP_DEFLATED`, `ZIP_BZIP2` or `ZIP_LZMA` is specified but the corresponding module (`zlib`, `bz2` or `lzma`) is not available, `RuntimeError` is also raised. 默认值为`ZIP_STORED`。如果allowZip64是`True`（默认值）zip文件将创建ZIP文件，当zip文件大于2 GiB时使用ZIP64扩展。如果为false，则当ZIP文件需要ZIP64扩展时，`zipfile`将引发异常。

  如果使用模式`'w'`，`'x'`或`'a'`创建文件，然后按`closed`将任何文件添加到归档中，空归档的相应ZIP结构将被写入文件。

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

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

  版本3.2中的新功能：添加了使用`ZipFile`作为上下文管理器的功能。

  在版本3.3中已更改：添加了对`bzip2`和`lzma`压缩的支持。

  在版本3.4中更改： ZIP64扩展名默认情况下已启用。

  在3.5版本中进行了更改：添加了对写入不可搜索流的支持。添加了对`'x'`模式的支持。

`ZipFile.``close`()

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

`ZipFile.``getinfo`(name)

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

`ZipFile.``infolist`()

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

`ZipFile.``namelist`()

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

`ZipFile.``open`(name, mode='r', pwd=None)

  从归档中提取成员作为文件状对象（ZipExtFile）。名称是档案中文件的名称，或`ZipInfo`对象。The mode parameter, if included, must be one of the following: `'r'` (the default), `'U'`, or `'rU'`. 选择`'U'`或`'rU'`将在只读对象中启用universal newlines支持。pwd是用于加密文件的密码。在封闭的ZipFile上调用`open()`会引发`RuntimeError`。

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

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

  注意

  类文件对象是只读的并提供以下方法：`read()`，`readline()`，`readlines()`，`__iter__()`，`__next__()`。

  注意

  `open()`返回的对象可以独立于ZipFile操作。

  注意

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

  从版本3.4开始弃用，将在版本3.6中删除： `'U'`或`'rU'`模式。使用`io.TextIOWrapper`在universal newlines模式下读取压缩文本文件。

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

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

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

  注意

  如果成员文件名是绝对路径，则驱动器/ UNC共享点和前导（后）斜杠将被去除。：`///foo/bar`在Unix上变为`foo/bar`，并且`C:\foo\bar`变为`foo\bar` 并且将删除成员文件名中的所有`".."`组件。: `../../foo../../ba..r` becomes `foo../ba..r`. On Windows illegal characters (`:`, `<`, `>`, `|`, `"`, `?`, and `*`) replaced by underscore (`_`).

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

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

  警告

  切勿在未经预先检查的情况下从不可信来源中提取存档。可能在路径之外创建文件，例如具有以`"/"`开头的绝对文件名的成员或具有两个点`".."`的文件名。此模块尝试阻止。请参阅`extract()`注意。

`ZipFile.``printdir`()

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

`ZipFile.``setpassword`(pwd)

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

`ZipFile.``read`(name, pwd=None)

  返回归档中文件名称的字节。名称是档案中文件的名称，或`ZipInfo`对象。归档必须打开以进行读取或追加。pwd是用于加密文件的密码，如果指定，它将覆盖使用`setpassword()`设置的默认密码。在封闭的ZipFile上调用`read()`会引发`RuntimeError`。Calling `read()` on a ZipFile that uses a compression method other than `ZIP_STORED`, `ZIP_DEFLATED`, `ZIP_BZIP2` or `ZIP_LZMA` will raise a `NotImplementedError`. 如果相应的压缩模块不可用，也会出现错误。

`ZipFile.``testzip`()

  读取归档中的所有文件，并检查其CRC和文件头。返回第一个坏文件的名称，否则返回`None`。在封闭的ZipFile上调用`testzip()`会引发`RuntimeError`。

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

  将名为filename的文件写入归档文件，给它归档名称arcname（默认情况下，这将与filename相同，驱动器盘符，并删除了导向路径分隔符）。如果给定，compress_type会覆盖为新条目的构造函数为压缩参数指定的值。The archive must be open with mode `'w'`, `'x'` or `'a'` – calling `write()` on a ZipFile created with mode `'r'` will raise a `RuntimeError`. 在封闭的ZipFile上调用`write()`会引发`RuntimeError`。

  注意

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

  注意

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

  注意

  如果`arcname`（或`filename`，如果未给出`arcname`）包含空字节，则归档中的文件名称将被截断空字节。

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

  将字符串数据写入归档； zinfo_or_arcname是档案中的档案名称，或是`ZipInfo`实例。如果它是一个实例，至少必须给出文件名，日期和时间。如果是名称，则日期和时间设置为当前日期和时间。The archive must be opened with mode `'w'`, `'x'` or `'a'` – calling `writestr()` on a ZipFile created with mode `'r'` will raise a `RuntimeError`. 在封闭的ZipFile上调用`writestr()`会引发`RuntimeError`。

  如果给定，compress_type会覆盖为新条目的构造函数或zinfo_or_arcname中给出的压缩参数的值（如果是`ZipInfo`实例）。

  注意

  When passing a `ZipInfo` instance as the zinfo_or_arcname parameter, the compression method used will be that specified in the compress_type member of the given `ZipInfo` instance. 默认情况下，`ZipInfo`构造函数将此成员设置为`ZIP_STORED`。

  在版本3.2中更改： compress_type参数。

还提供以下数据属性：

`ZipFile.``debug`

  要使用的调试输出的级别。这可以从`0`（默认值，无输出）设置为`3`（最大输出）。调试信息写入`sys.stdout`。

`ZipFile.``comment`

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

## 13.5.2. PyZipFile Objects

`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`并将相应的文件添加到存档。

    如果未给出`PyZipFile`的optimize参数或`-1`，则相应的文件为`*.pyc`文件，如有必要，进行编译。

    If the optimize parameter to `PyZipFile` was `0`, `1` or `2`, only files with that optimization level (see `compile()`) are added to the archive, compiling if necessary.

    如果pathname是文件，则文件名必须以`.py`结尾，并且只添加（对应的`*.py[co]`如果路径名是不以`.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 Objects

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

实例具有以下属性：

`ZipInfo.``filename`

  归档中的文件的名称。

`ZipInfo.``date_time`

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

  指数 | 值
  --- | ---
  `0` | 年（> = 1980）
  `1` | 月（从1个月）
  `2` | 日（月份）
  `3` | 小时（从零开始）
  `4` | 分钟（从零开始）
  `5` | 秒（从零开始）

  注意

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

`ZipInfo.``compress_type`

  归档成员的压缩类型。

`ZipInfo.``comment`

  个人档案成员的注释。

`ZipInfo.``extra`

  扩展字段数据。PKZIP应用程序注释包含对此字符串中包含的数据的内部结构的一些注释。

`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`

  未压缩文件的大小。