zipfile —使用 ZIPFiles

源代码: Lib/zipfile.py


ZIP 文件格式是一种常见的存档和压缩标准。该模块提供了用于创建,读取,写入,附加和列出 ZIP 文件的工具。对该模块的任何高级用法都需要了解PKZIP 应用说明中定义的格式。

该模块当前不处理多磁盘 ZIP 文件。它可以处理使用 ZIP64extensions 的 ZIP 文件(即,大小超过 4 GiB 的 ZIP 文件)。它支持对 ZIP 存档中的加密文件进行解密,但是当前无法创建加密文件。解密非常慢,因为它是在本机 Python 中而不是 C 中实现的。

该模块定义以下各项:

  • exception zipfile. BadZipFile
    • 错误的 ZIP 文件引发的错误。

3.2 版中的新Function。

  • exception zipfile. BadZipfile
    • BadZipFile的别名,用于与旧版本的 Python 兼容。

从 3.2 版开始不推荐使用。

  • exception zipfile. LargeZipFile

    • 当 ZIP 文件需要 ZIP64 Function但尚未启用时引发的错误。
  • zipfile. ZipFile

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

    • zip 文件的 pathlib 兼容包装器。有关详细信息,请参见第Path Objects节。

3.8 版的新Function。

  • zipfile. PyZipFile

    • 用于创建包含 Python 库的 ZIP 归档文件的类。
    • class * zipfile. ZipInfo(* filename ='NoName' date_time =(1980 1 1 0 0 0)*)
    • 用于表示有关存档成员的信息的类。此类的实例由ZipFile个对象的getinfo()infolist()方法返回。 zipfile模块的大多数用户将不需要创建它们,而仅使用此模块创建的那些。 * filename 应该是存档成员的全名, date_time *应该是一个包含六个字段的 Tuples,这些字段描述了文件的最后修改时间; ZipInfo Objects部分中描述了这些字段。
  • zipfile. is_zipfile(* filename *)

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

在版本 3.1 中更改:支持文件和类似文件的对象。

  • zipfile. ZIP_STORED

    • 未压缩的存档成员的数字常数。
  • zipfile. ZIP_DEFLATED

    • 常用 ZIP 压缩方法的数字常数。这需要zlib模块。
  • zipfile. ZIP_BZIP2

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

版本 3.3 中的新Function。

  • zipfile. ZIP_LZMA
    • LZMA 压缩方法的数字常数。这需要lzma模块。

版本 3.3 中的新Function。

Note

ZIP 文件格式规范自 2001 年以来就包括对 bzip2 压缩的支持,从 2006 年以来就包括对 LZMA 压缩的支持。但是,某些工具(包括较旧的 Python 版本)不支持这些压缩方法,或者可能完全拒绝处理 ZIP 文件,或者无法提取单个文件。

See also

  • PKZIP 应用说明

  • ZIP 文件格式的文档,作者是 Phil Katz,他是该格式和算法的创建者。

  • Info-ZIP 主页

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

ZipFile Objects

    • class * zipfile. ZipFile(* file mode ='r' compression = ZIP_STORED allowZip64 = True compresslevel = None **,* strict_timestamps = True *)
    • 打开一个 ZIP 文件,其中* file *可以是文件(字符串),类似文件的对象或path-like object的路径。
  • 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

如果* allowZip64 *为True(默认值),则 zipfile 会创建一个 ZIP 文件,当 zipfile 大于 4 GiB 时,将使用 ZIP64extensions。如果是false,则zipfile将引发异常,当 ZIP 文件需要 ZIP64extensions 时。

  • compresslevel *参数控制将文件写入存档时要使用的压缩级别。使用ZIP_STOREDZIP_LZMA时无效。使用ZIP_DEFLATED时,可接受09的整数(有关更多信息,请参见zlib)。使用ZIP_BZIP2时,可接受19的整数(有关更多信息,请参见bz2)。

  • strict_timestamps *参数设置为False时,允许压缩早于 1980-01-01 的文件,但需要将时间戳设置为 1980-01-01.对于高于 2107-12-31 的文件,也会发生类似的行为,时间戳也设置为限制。

如果在模式'w''x''a'然后是closed的模式下创建文件,而未将任何文件添加到存档中,则用于空存档的适当 ZIP 结构将被写入该文件。

ZipFile 还是上下文 Management 器,因此支持with语句。在示例中,* myzip *在with语句的套件完成后关闭-即使发生异常:

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

版本 3.2 中的新Function:添加了使用ZipFile作为上下文 Management 器的Function。

在版本 3.3 中进行了更改:添加了对bzip2lzma压缩的支持。

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

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

在版本 3.6 中进行了更改:以前,对于无法识别的压缩值,提出了一个普通的RuntimeError

在版本 3.6.2 中更改:* file *参数接受path-like object

在 3.7 版中进行了更改:添加* compresslevel *参数。

3.8 版中的新Function:* strict_timestamps *仅关键字参数

  • ZipFile. close ( )

    • 关闭存档文件。您必须先退出close(),然后退出程序,否则基本记录将不会被写入。
  • ZipFile. getinfo(* name *)

    • 返回一个ZipInfo对象,其中包含有关存档成员* name *的信息。调用getinfo()以获取当前未包含在 Files 中的名称将引发KeyError
  • ZipFile. infolist ( )

    • 为 Files 的每个成员返回一个包含ZipInfo对象的列表。如果打开了现有存档,则对象的 Sequences 与它们在磁盘上实际 ZIP 文件中的条目的 Sequences 相同。
  • ZipFile. namelist ( )

    • 按名称返回存档成员列表。
  • ZipFile. open(* name mode ='r' pwd = None **,* force_zip64 = False *)

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

open()也是上下文 Management 器,因此支持with语句:

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

使用* mode * 'r'时,类似文件的对象(ZipExtFile)是只读的,并提供以下方法:read()readline()readlines()seek()tell()iter()next()。这些对象可以独立于 ZipFile 运行。

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

写入文件时,如果文件大小事先未知,但可能超过 2 GiB,则传递force_zip64=True以确保头格式能够支持大文件。如果文件大小事先已知,则构造一个file_size设置的ZipInfo对象,并将其用作* name *参数。

Note

open()read()extract()方法可以使用文件名或ZipInfo对象。当您try读取包含名称重复的成员的 ZIP 文件时,您将不胜感激。

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

在 3.6 版中进行了更改:open()现在可用于passmode='w'选项将文件写入存档。

在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用open()将引发ValueError。以前,提出了RuntimeError

  • ZipFile. extract(* member path = None pwd = None *)
    • 从存档中提取成员到当前工作目录; * member *必须是其全名或ZipInfo对象。尽可能准确地提取其文件信息。 * path *指定要提取到的其他目录。 * member *可以是文件名或ZipInfo对象。 * pwd *是用于加密文件的密码。

返回创建的规范化路径(目录或新文件)。

Note

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

在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用extract()将引发ValueError。以前,提出了RuntimeError

在版本 3.6.2 中更改:* path *参数接受path-like object

  • ZipFile. extractall(* path = None members = None pwd = None *)
    • 将所有成员从存档提取到当前工作目录。 * path *指定要提取到的其他目录。 * members *是可选的,并且必须是namelist()返回的列表的子集。 * pwd *是用于加密文件的密码。

Warning

未经事先检查,切勿从不受信任的来源中提取 Files。文件可能是在* path *之外创建的,例如具有以"/"开头的绝对文件名或带有两个点".."的文件名的成员。该模块试图防止这种情况。请参阅extract()注意。

在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用extractall()将引发ValueError。以前,提出了RuntimeError

在版本 3.6.2 中更改:* path *参数接受path-like object

  • ZipFile. printdir ( )

    • 将目录的目录打印到sys.stdout
  • ZipFile. setpassword(* pwd *)

    • 将* pwd *设置为默认密码以提取加密文件。
  • ZipFile. read(* name pwd = None *)

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

在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用read()将引发ValueError。以前,提出了RuntimeError

  • ZipFile. testzip ( )
    • 读取存档中的所有文件,并检查其 CRC 和文件头。返回第一个错误文件的名称,否则返回None

在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用testzip()将引发ValueError。以前,提出了RuntimeError

  • ZipFile. write(* filename arcname = None compress_type = None compresslevel = None *)
    • 将名为* filename 的文件写入存档,并为其指定存档名称 arcname (默认情况下,该名称与 filename 相同,但不带驱动器号,并且删除前导路径分隔符)。如果给定, compress_type 将为新条目的构造函数覆盖为 compression 参数指定的值。同样,如果指定, compresslevel *将覆盖构造函数。存档必须以'w''x''a'模式打开。

Note

存档名称应相对于存档根目录,即,它们不应以路径分隔符开头。

Note

如果arcname(或filename,如果未提供arcname)包含一个空字节,则存档中文件的名称将在该空字节处被截断。

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

  • ZipFile. writestr(* zinfo_or_arcname data compress_type = None compresslevel = None *)
    • 将文件写入存档。内容是* data *,它可以是strbytes实例;如果它是str,则首先将其编码为 UTF-8. * zinfo_or_arcname *是将在归档文件中给出的文件名,或者是ZipInfo实例。如果是实例,则至少必须提供文件名,日期和时间。如果是名称,则将日期和时间设置为当前日期和时间。必须以'w''x''a'模式打开 Files。

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

Note

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

在版本 3.2 中更改:* compress_type *参数。

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

以下数据属性也可用:

  • ZipFile. filename

    • ZIP 文件的名称。
  • ZipFile. debug

    • 要使用的调试输出级别。可以将其设置为0(默认,无输出)到3(最多输出)。调试信息被写入sys.stdout
  • ZipFile. comment

    • 与 ZIP 文件关联的 Comments 为bytes对象。如果将 Comments 分配给以'w''x''a'模式创建的ZipFile实例,则 Comments 的长度不得超过 65535 字节。超过此长度的 Comment 将被截断。

Path Objects

    • class * zipfile. Path(* root at =''*)
    • rootzipfile(可以是ZipFile实例或file适合传递到ZipFile构造函数)中构造 Path 对象。

at指定此路径在 zip 文件中的位置,例如'dir/file.txt','dir /'或''。默认为空字符串,表示根。

路径对象公开了pathlib.Path个对象的以下Function:

路径对象可使用/运算符遍历。

  • Path. name

    • finally路径组件。
  • Path. open ( * , ** )

Caution

此函数的签名在 Python 3.9 中以不兼容的方式更改。对于将来兼容的版本,请考虑使用第三方 zipp.Path 软件包(3.0 或更高版本)。

  • Path. iterdir ( )

    • 枚举当前目录的子级。
  • Path. is_dir ( )

    • 如果当前上下文引用目录,则返回True
  • Path. is_file ( )

    • 如果当前上下文引用文件,则返回True
  • Path. exists ( )

    • 如果当前上下文引用了 zip 文件中的文件或目录,则返回True
  • Path. read_text ( * , ** )

    • 以 unicode 文本读取当前文件。位置参数和关键字参数传递给io.TextIOWrapper(上下文所隐含的buffer除外)。
  • Path. read_bytes ( )

    • 以字节为单位读取当前文件。

PyZipFile Objects

PyZipFile构造函数的参数与ZipFile构造函数的参数相同,另外一个参数* optimize *。

    • class * zipfile. PyZipFile(* file mode ='r' compression = ZIP_STORED allowZip64 = True optimize = -1 *)
    • 3.2 版中的新Function:* optimize *参数。

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

实例除ZipFile对象之外,还有一种方法:

  • writepy(* pathname basename ='' filterfunc = None *)
    • 搜索文件*.py并将相应的文件添加到存档中。

如果未提供PyZipFile-1的* optimize *参数,则对应的文件是*.pyc文件,并在必要时进行编译。

如果PyZipFile的* optimize *参数是012,则仅将具有该优化级别(请参见compile())的文件添加到存档中,并在必要时进行编译。

如果* pathname 是文件,则文件名必须以.py结尾,并且仅在顶层添加(对应的*.pyc)文件(没有路径信息)。如果 pathname *是不以.py结尾的文件,则将引发RuntimeError。如果它是目录,并且该目录不是软件包目录,那么所有文件*.pyc都将添加到顶层。如果该目录是程序包目录,则所有*.pyc都将作为文件路径添加到程序包名称下,如果任何子目录是程序包目录,则所有这些都将按排序 Sequences 递归添加。

  • basename *仅供内部使用。

  • filterfunc (如果给定的话)必须是带有单个字符串参数的函数。在将其添加到存档之前,它将pass每个路径(包括每个单独的完整文件路径)传递。如果 filterfunc 返回假值,则不会添加该路径,如果它是目录,则其内容将被忽略。例如,如果我们的测试文件全部位于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 版中的新Function:* filterfunc *参数。

在版本 3.6.2 中更改:* pathname *参数接受path-like object

在版本 3.7 中更改:递归对目录条目进行排序。

ZipInfo Objects

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

有一种方法可以为文件系统文件创建ZipInfo实例:

    • classmethod * ZipInfo. from_file(* filename arcname = None **,* strict_timestamps = True *)
    • 为文件系统上的文件构造一个ZipInfo实例,以准备将其添加到 zip 文件中。
  • filename *应该是文件系统上文件或目录的路径。

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

  • strict_timestamps *参数设置为False时,允许压缩早于 1980-01-01 的文件,但需要将时间戳设置为 1980-01-01.对于高于 2107-12-31 的文件,也会发生类似的行为,时间戳也设置为限制。

3.6 版的新Function。

在版本 3.6.2 中更改:* filename *参数接受path-like object

3.8 版中的新Function:* strict_timestamps *仅关键字参数

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

  • ZipInfo. is_dir ( )
    • 如果此存档成员是目录,则返回True

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

3.6 版的新Function。

  • ZipInfo. filename

    • 存档中文件的名称。
  • ZipInfo. date_time

    • 最后一次修改存档成员的时间和日期。这是六个值的 Tuples:
IndexValue
0年(> = 1980)
1Month (one-based)
2一个月中的某天(基于 1 天)
3Hours (zero-based)
4Minutes (zero-based)
5Seconds (zero-based)

Note

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

  • ZipInfo. compress_type

    • 存档成员的压缩类型。
  • ZipInfo. comment

    • bytes对象的形式 Comments 单个存档成员。
  • ZipInfo. extra

    • 扩展字段数据。 PKZIP 应用说明包含对该bytes对象中包含的数据的内部结构的一些 Comments。
  • ZipInfo. create_system

    • 创建 ZIP 归档文件的系统。
  • ZipInfo. create_version

    • 创建 ZIP 存档的 PKZIP 版本。
  • ZipInfo. extract_version

    • 提取存档所需的 PKZIP 版本。
  • ZipInfo. reserved

    • 必须为零。
  • ZipInfo. flag_bits

    • ZIP 标志位。
  • ZipInfo. volume

    • 文件头的卷号。
  • ZipInfo. internal_attr

    • Internal attributes.
  • ZipInfo. external_attr

    • 外部文件属性。
  • ZipInfo. header_offset

    • 文件头的字节偏移量。
  • ZipInfo. CRC

    • 未 zipfile 的 CRC-32.
  • ZipInfo. compress_size

    • 压缩数据的大小。
  • ZipInfo. file_size

    • 未 zipfile 的大小。

Command-Line Interface

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

Command-line options

  • -l <zipfile>

  • --list <zipfile>

    • 列出 zipfile 中的文件。
  • -c <zipfile> <source1> ... <sourceN>

  • --create <zipfile> <source1> ... <sourceN>

    • 从源文件创建 zipfile。
  • -e <zipfile> <output_dir>

  • --extract <zipfile> <output_dir>

    • 将 zipfile 解压缩到目标目录。
  • -t <zipfile>

  • --test <zipfile>

    • 测试 zipfile 是否有效。

Decompression pitfalls

zipfile 模块中的提取可能由于以下列出的一些陷阱而失败。

来自文件本身

由于密码不正确/ CRC 校验和/ ZIP 格式或不支持的压缩方法/解密,解压缩可能会失败。

文件系统限制

在不同文件系统上的限制可能会导致解压缩失败。例如目录条目中的允许字符,文件名的长度,路径名的长度,单个文件的大小以及文件数等。

Resources limitations

内存或磁盘容量不足会导致解压缩失败。例如,解压缩炸弹(也称为ZIP bomb)应用于 zipfile 库,这可能导致磁盘卷用尽。

Interruption

解压缩过程中的break(例如按 Control-C 或终止解压缩过程)可能会导致存档的解压缩不完全。

提取的默认行为

不知道默认的提取行为会导致意外的减压结果。例如,两次提取相同的归档文件时,它将覆盖文件而无需询问。