zipfile ---使用Zip存档

源代码: Lib/zipfile.py


zip文件格式是一种常见的存档和压缩标准。此模块提供创建、读取、写入、附加和列出zip文件的工具。本模块的任何高级使用都需要了解格式,如 PKZIP Application Note .

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

该模块定义了以下各项:

exception zipfile.BadZipFile

为不正确的zip文件引发的错误。

3.2 新版功能.

exception zipfile.BadZipfile

Alias BadZipFile ,以便与旧的python版本兼容。

3.2 版后已移除.

exception zipfile.LargeZipFile

当zip文件需要zip64功能但尚未启用时引发的错误。

class zipfile.ZipFile

用于读取和写入zip文件的类。见节 zip文件对象 以获取构造函数详细信息。

class zipfile.Path

与pathlib兼容的zip文件包装。参见第节 路径对象 有关详细信息。

3.8 新版功能.

class zipfile.PyZipFile

用于创建包含python库的zip存档的类。

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

类,用于表示有关存档成员的信息。此类的实例由 getinfo()infolist() 方法 ZipFile 物体。的大多数用户 zipfile 模块不需要创建这些,但只使用由该模块创建的。 filename 应该是存档成员的全名,并且 date_time 应该是一个包含六个字段的元组,这些字段描述了文件最后一次修改的时间;这些字段在第节中进行了描述。 ZIPFIN对象 .

zipfile.is_zipfile(filename)

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

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

zipfile.ZIP_STORED

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

zipfile.ZIP_DEFLATED

常用压缩方法的数值常量。这需要 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

文件的压缩文件格式由菲尔卡茨,格式和算法的创建者使用。

Info-ZIP Home Page

有关info-zip项目的zip存档程序和开发库的信息。

zip文件对象

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 引用现有文件,a FileExistsError 将被引发。如果 mode'a'file 引用现有的zip文件,然后向其中添加其他文件。如果 file 不引用zip文件,则会将新的zip存档追加到该文件中。这是为了向另一个文件(如 python.exe )如果 mode'a' 文件根本不存在,它是被创建的。如果 mode'r''a' ,文件应该是可查找的。

压缩 是在写入存档文件时要使用的zip压缩方法,并且应该是 ZIP_STOREDZIP_DEFLATEDZIP_BZIP2ZIP_LZMA ;无法识别的值将导致 NotImplementedError 被引发。如果 ZIP_DEFLATEDZIP_BZIP2ZIP_LZMA 是指定的,但对应的模块 (zlibbz2lzma )不可用, RuntimeError 提高了。默认值为 ZIP_STORED .

如果 允许ZIP64True (默认)当zipfile大于4 gib时,zipfile将创建使用zip64扩展名的zip文件。如果是 false zipfile 当zip文件需要zip64扩展名时,将引发异常。

这个 压缩能级 参数控制将文件写入存档时要使用的压缩级别。使用时 ZIP_STOREDZIP_LZMA 它没有效果。使用时 ZIP_DEFLATED 整数 0 通过 9 被接受(见 zlib 更多信息)。使用时 ZIP_BZIP2 整数 1 通过 9 被接受(见 bz2 更多信息)。

这个 strict_timestamps 参数,设置为时 False ,允许压缩早于1980-01-01的文件,代价是将时间戳设置为1980-01-01。类似的行为发生在比2107-12-31更新的文件中,时间戳也被设置为限制。

如果文件是用模式创建的 '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 为无法识别的压缩值引发。

在 3.6.2 版更改: 这个 file 参数接受 path-like object .

在 3.7 版更改: 添加 压缩能级 参数。

3.8 新版功能: 这个 strict_timestamps 仅关键字参数

ZipFile.close()

关闭存档文件。你必须调用 close() 退出程序前,不会写入重要记录。

ZipFile.getinfo(name)

返回A ZipInfo 包含有关存档成员信息的对象 name . 调用 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()seek()tell()__iter__()__next__() . 这些对象可以独立于zipfile操作。

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

写入文件时,如果事先不知道文件大小,但可能超过2 GiB,则通过 force_zip64=True 以确保头格式能够支持大型文件。如果预先知道文件大小,请构造 ZipInfo 对象与 file_size 设置,并将其用作 name 参数。

注解

这个 open()read()extract() 方法可以采用文件名或 ZipInfo 对象。当您试图读取包含具有重复名称的成员的zip文件时,您将非常感激。

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

在 3.6 版更改: open() 现在可以使用 mode='w' 选择权。

在 3.6 版更改: 调用 open() 在关闭的ZipFile上 ValueError . 以前,A RuntimeError 提高了。

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

将存档中的成员提取到当前工作目录中; 成员 必须是其全名或 ZipInfo 对象。它的文件信息被尽可能准确地提取出来。 path 指定要提取到的其他目录。 成员 可以是文件名或 ZipInfo 对象。 pwd 是用于加密文件的密码。

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

注解

如果成员文件名是绝对路径,则驱动器/UNC SharePoint和前导(后)斜杠将被删除,例如: ///foo/bar becomes foo/bar on Unix, and C:\foo\bar becomes foo\bar on Windows. And all ".." components in a member filename will be removed, e.g.: ../../foo../../ba..r becomes foo../ba..r. On Windows illegal characters (:, `` < >|"?* )替换为下划线 (_

在 3.6 版更改: 调用 extract() 在关闭的ZipFile上 ValueError . 以前,A RuntimeError 提高了。

在 3.6.2 版更改: 这个 path 参数接受 path-like object .

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

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

警告

未经事先检查,不得从不受信任的来源提取档案。文件可能是在 path ,例如,绝对文件名以 "/" 或带有两个点的文件名 ".." . 本模块试图防止这种情况发生。见 extract() 注意。

在 3.6 版更改: 调用 extractall() 在关闭的ZipFile上 ValueError . 以前,A RuntimeError 提高了。

在 3.6.2 版更改: 这个 path 参数接受 path-like object .

ZipFile.printdir()

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

ZipFile.setpassword(pwd)

集合 pwd 作为提取加密文件的默认密码。

ZipFile.read(name, pwd=None)

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

在 3.6 版更改: 调用 read() 在关闭的ZipFile上 ValueError . 以前,A RuntimeError 提高了。

ZipFile.testzip()

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

在 3.6 版更改: 调用 testzip() 在关闭的ZipFile上 ValueError . 以前,A RuntimeError 提高了。

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

写入名为的文件 filename 到档案馆,给它一个档案馆的名字 弧名 (默认情况下,这将与 filename ,但没有驱动器号,并且删除了前导路径分隔符)。如果给出的话, compress_type 覆盖为 压缩 新项的构造函数的参数。同样地, 压缩能级 如果给定,将重写构造函数。存档必须以模式打开 'w''x''a' .

注解

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

注解

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

在 3.6 版更改: 调用 write() 在使用模式创建的ZipFile上 'r' 或者一个关闭的zipfile将引发 ValueError . 以前,A RuntimeError 提高了。

ZipFile.writestr(zinfo_or_arcname, data, compress_type=None, compresslevel=None)

将文件写入存档。内容是 data ,可以是 str 或A bytes 实例;如果是 str ,首先将其编码为UTF-8。 zinfo_or_arcname 是将在存档中提供的文件名,还是 ZipInfo 实例。如果它是一个实例,至少必须给出文件名、日期和时间。如果是名称,则日期和时间设置为当前日期和时间。必须以模式打开存档 'w''x''a' .

如果给出的话, compress_type 覆盖为 压缩 新项的构造函数的参数,或 zinfo_or_arcname (如果那是 ZipInfo 实例)。同样地, 压缩能级 如果给定,将重写构造函数。

注解

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

在 3.2 版更改: 这个 compress_type 参数。

在 3.6 版更改: 调用 writestr() 在使用模式创建的ZipFile上 'r' 或者一个关闭的zipfile将引发 ValueError . 以前,A RuntimeError 提高了。

以下数据属性也可用:

ZipFile.filename

zip文件的名称。

ZipFile.debug

要使用的调试输出级别。这可能是从 0 (默认,无输出)到 3 (最大输出)。调试信息写入 sys.stdout .

ZipFile.comment

与zip文件关联的注释 bytes 对象。如果将注释分配给 ZipFile 使用模式创建的实例 'w''x''a' ,不应超过65535字节。超过此长度的注释将被截断。

路径对象

class zipfile.Path(root, at='')

root 压缩文件(可能是 ZipFile 实例或 file 适合传给 ZipFile 构造函数)。

at 指定此路径在zipfile中的位置,例如“dir/file.txt”、“dir/”或“”。默认为空字符串,指示根。

路径对象公开的以下功能 pathlib.Path 物体:

路径对象可以使用 / 运算符或 joinpath

Path.name

最后一个路径组件。

Path.open(mode='r', *, pwd, **)

援引 ZipFile.open() 在当前路径上。允许通过支持的模式“r”、“w”、“rb”、“wb”打开读或写、文本或二进制文件。位置参数和关键字参数传递给 io.TextIOWrapper 以文本形式打开,否则忽略。 pwdpwd 参数到 ZipFile.open() .

在 3.9 版更改: 增加了对文本和二进制模式的支持。默认模式现在是文本。

Path.iterdir()

枚举当前目录的子目录。

Path.is_dir()

返回 True 如果当前上下文引用目录。

Path.is_file()

返回 True 如果当前上下文引用文件。

Path.exists()

返回 True 如果当前上下文引用了zip文件中的文件或目录。

Path.read_text(*, **)

将当前文件读取为Unicode文本。位置参数和关键字参数传递给 io.TextIOWrapper (除外) buffer 这是上下文所隐含的)。

Path.read_bytes()

以字节形式读取当前文件。

Path.joinpath(*other)

返回一个新的路径对象,每个 其他 加入了参数。以下各项等效:

>>> Path(...).joinpath('child').joinpath('grandchild')
>>> Path(...).joinpath('child', 'grandchild')
>>> Path(...) / 'child' / 'grandchild'

在 3.10 版更改: 在3.10之前, joinpath 没有记录并且只接受了一个参数。

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

如果 optimize 参数到 PyZipFile 没有给予或 -1 ,对应的文件是 *.pyc 文件,必要时编译。

如果 optimize 参数到 PyZipFile012 ,仅限具有该优化级别的文件(请参见 compile() )添加到存档中,必要时进行编译。

如果 路径名 是一个文件,文件名必须以 .py 和(对应的 *.pyc )文件是在顶层添加的(没有路径信息)。如果 路径名 不是以结尾的文件 .py ,A RuntimeError 将被引发。如果它是一个目录,而该目录不是包目录,则所有文件 *.pyc 在顶层添加。如果目录是包目录,则全部 *.pyc 以文件路径的形式添加到包名称下,如果任何子目录是包目录,则所有子目录都按顺序递归添加。

基名 仅供内部使用。

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

>>> 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 新版功能: 这个 菲尔特芬克 参数。

在 3.6.2 版更改: 这个 路径名 参数接受 path-like object .

在 3.7 版更改: 递归对目录项排序。

ZIPFIN对象

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

有一个类方法可以使 ZipInfo 文件系统文件的实例:

classmethod ZipInfo.from_file(filename, arcname=None, *, strict_timestamps=True)

构建一个 ZipInfo 例如,文件系统上的一个文件,为将其添加到zip文件做准备。

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

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

这个 strict_timestamps 参数,设置为时 False ,允许压缩早于1980-01-01的文件,代价是将时间戳设置为1980-01-01。类似的行为发生在比2107-12-31更新的文件中,时间戳也被设置为限制。

3.6 新版功能.

在 3.6.2 版更改: 这个 filename 参数接受 path-like object .

3.8 新版功能: 这个 strict_timestamps 仅关键字参数

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

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

将单个存档成员作为 bytes 对象。

ZipInfo.extra

扩展字段数据。这个 PKZIP Application Note 包含有关此中包含的数据的内部结构的一些注释 bytes 对象。

ZipInfo.create_system

创建zip存档的系统。

ZipInfo.create_version

创建zip存档的pkzip版本。

ZipInfo.extract_version

提取存档文件需要pkzip版本。

ZipInfo.reserved

必须是零。

ZipInfo.flag_bits

标记标志位。

ZipInfo.volume

文件头的卷号。

ZipInfo.internal_attr

内部属性。

ZipInfo.external_attr

外部文件属性。

ZipInfo.header_offset

文件头的字节偏移量。

ZipInfo.CRC

未压缩文件的CRC-32。

ZipInfo.compress_size

压缩数据的大小。

ZipInfo.file_size

未压缩文件的大小。

命令行界面

这个 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

命令行选项

-l <zipfile>
--list <zipfile>

列出压缩文件中的文件。

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

从源文件创建zipfile。

-e <zipfile> <output_dir>
--extract <zipfile> <output_dir>

将zipfile提取到目标目录中。

-t <zipfile>
--test <zipfile>

测试ZipFile是否有效。

减压陷阱

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

从文件本身

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

文件系统限制

超过不同文件系统的限制可能会导致解压缩失败。例如目录项中允许的字符、文件名的长度、路径名的长度、单个文件的大小和文件数等。

资源限制

内存或磁盘卷不足将导致解压缩失败。例如,减压炸弹 ZIP bomb )应用于可能导致磁盘卷耗尽的zipfile库。

中断

解压过程中的中断,如按下control-C或终止解压过程,可能会导致不完整的档案解压。

提取的默认行为

不知道默认的提取行为可能会导致意外的解压缩结果。例如,当提取同一个存档文件两次时,它会不经请求而覆盖文件。