zipfile
- 处理 ZIP 归档¶
源代码: Lib/zipfile/
ZIP 文件格式是一种常见的归档和压缩标准。此模块提供了创建、读取、写入、追加和列出 ZIP 文件的工具。要高级使用此模块,需要了解 PKZIP 应用说明 中定义的格式。
此模块当前不处理多磁盘 ZIP 文件。它可以处理使用 ZIP64 扩展名的 ZIP 文件(即大小超过 4 GiB 的 ZIP 文件)。它支持解密 ZIP 归档中的加密文件,但目前无法创建加密文件。解密速度非常慢,因为它是在原生 Python 而不是 C 中实现的。
该模块定义了以下项目
- 异常 zipfile.BadZipFile¶
针对错误的 ZIP 文件引发的错误。
3.2 版新增。
- 异常 zipfile.BadZipfile¶
BadZipFile
的别名,用于与旧版 Python 兼容。3.2 版后已弃用。
- 异常 zipfile.LargeZipFile¶
当 ZIP 文件需要 ZIP64 功能但尚未启用时引发的错误。
- 类 zipfile.ZipFile
用于读取和写入 ZIP 文件的类。有关构造函数的详细信息,请参阅 ZipFile 对象 部分。
- 类 zipfile.Path
实现
pathlib.Path
提供的接口子集的类,包括完整的importlib.resources.abc.Traversable
接口。3.8 版新增。
- 类 zipfile.PyZipFile
用于创建包含 Python 库的 ZIP 归档的类。
- 类 zipfile.ZipInfo(filename='NoName', date_time=(1980, 1, 1, 0, 0, 0))¶
用于表示有关归档成员的信息的类。此类的实例由
getinfo()
和infolist()
方法返回ZipFile
对象。大多数zipfile
模块的用户不需要创建这些实例,只需使用此模块创建的实例即可。 filename 应该是归档成员的全名,date_time 应该是一个包含六个字段的元组,用于描述对文件进行最后修改的时间;这些字段在 ZipInfo 对象 部分中有描述。
- zipfile.is_zipfile(filename)¶
如果 filename 根据其魔数是有效的 ZIP 文件,则返回
True
,否则返回False
。 filename 也可以是文件或类文件对象。在 3.1 版更改: 支持文件和类文件对象。
- zipfile.ZIP_STORED¶
未压缩归档成员的数字常量。
- zipfile.ZIP_LZMA¶
LZMA 压缩方法的数字常量。这需要
lzma
模块。3.3 版新增。
注意
ZIP 文件格式规范自 2001 年起就包含了对 bzip2 压缩的支持,自 2006 年起又包含了对 LZMA 压缩的支持。但是,某些工具(包括旧版本的 Python)不支持这些压缩方法,并且可能会拒绝处理整个 ZIP 文件,或者无法提取单个文件。
参见
- PKZIP 应用说明
ZIP 文件格式的创建者 Phil Katz 编写的关于该格式和所用算法的文档。
- Info-ZIP 主页
有关 Info-ZIP 项目的 ZIP 归档程序和开发库的信息。
ZipFile 对象¶
- class zipfile.ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True, compresslevel=None, *, strict_timestamps=True, metadata_encoding=None)¶
打开一个 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_STORED
、ZIP_DEFLATED
、ZIP_BZIP2
或ZIP_LZMA
;无法识别的值将导致引发NotImplementedError
。如果指定了ZIP_DEFLATED
、ZIP_BZIP2
或ZIP_LZMA
,但相应的模块(zlib
、bz2
或lzma
)不可用,则会引发RuntimeError
。默认值为ZIP_STORED
。如果 *allowZip64* 为
True
(默认值),则当 zipfile 大于 4 GiB 时,zipfile 将创建使用 ZIP64 扩展名的 ZIP 文件。如果为false
,则当 ZIP 文件需要 ZIP64 扩展名时,zipfile
将引发异常。*compresslevel* 参数控制将文件写入归档文件时要使用的压缩级别。使用
ZIP_STORED
或ZIP_LZMA
时,它不起作用。使用ZIP_DEFLATED
时,接受整数0
到9
(有关详细信息,请参阅zlib
)。使用ZIP_BZIP2
时,接受整数1
到9
(有关详细信息,请参阅bz2
)。*strict_timestamps* 参数设置为
False
时,允许压缩早于 1980-01-01 的文件,但代价是将时间戳设置为 1980-01-01。对于晚于 2107-12-31 的文件,也会出现类似的行为,时间戳也会设置为限制。当 mode 为
'r'
时,可以将 *metadata_encoding* 设置为编解码器的名称,该编解码器将用于解码元数据,例如成员的名称和 ZIP 注释。如果使用模式
'w'
、'x'
或'a'
创建文件,然后在未向归档文件添加任何文件的情况下closed
,则会将空归档文件的相应 ZIP 结构写入该文件。ZipFile 也是一个上下文管理器,因此支持
with
语句。在示例中,*myzip* 在with
语句的代码块完成后关闭,即使发生异常也是如此with ZipFile('spam.zip', 'w') as myzip: myzip.write('eggs.txt')
注意
*metadata_encoding* 是 ZipFile 的实例范围设置。当前无法针对每个成员设置此项。
此属性是针对旧实现的解决方法,这些实现生成的归档文件中的名称采用当前区域设置编码或代码页(主要是在 Windows 上)。根据 .ZIP 标准,可以通过归档文件头中的标志将元数据的编码指定为 IBM 代码页(默认值)或 UTF-8。该标志优先于 *metadata_encoding*,后者是 Python 特定的扩展。
版本 3.2 中的变化: 添加了将
ZipFile
用作上下文管理器的功能。版本 3.4 中的变化: 默认情况下启用 ZIP64 扩展名。
版本 3.5 中的变化: 添加了对写入不可查找流的支持。添加了对
'x'
模式的支持。3.6 版中的更改:之前,无法识别的压缩值会引发普通的
RuntimeError
。3.6.2 版中的更改:file 参数接受一个 类路径对象。
3.7 版中的更改:添加了 compresslevel 参数。
3.8 版中的更改:仅限关键字参数 strict_timestamps。
3.11 版中的更改:增加了对指定成员名称编码的支持,用于读取 zipfile 目录和文件头中的元数据。
- ZipFile.getinfo(name)¶
返回一个包含有关归档成员 name 信息的
ZipInfo
对象。如果打开的是现有归档,则对当前未包含在归档中的名称调用getinfo()
将引发KeyError
。
- ZipFile.namelist()¶
按名称返回归档成员列表。
- ZipFile.open(name, mode='r', pwd=None, *, force_zip64=False)¶
以二进制类文件对象的形式访问归档的成员。name 可以是归档中文件的名称,也可以是
ZipInfo
对象。mode 参数(如果包含)必须是'r'
(默认值)或'w'
。pwd 是用于解密加密 ZIP 文件的密码,作为bytes
对象。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
以确保标头格式能够支持大文件。如果文件大小事先已知,请构造一个设置了file_size
的ZipInfo
对象,并将其用作 name 参数。3.6 版中的更改:删除了对
mode='U'
的支持。使用io.TextIOWrapper
以 通用换行符 模式读取压缩文本文件。3.6 版中的更改:
ZipFile.open()
现在可以使用mode='w'
选项将文件写入归档。3.6 版中的更改:在关闭的 ZipFile 上调用
open()
将引发ValueError
。之前,会引发RuntimeError
。
- ZipFile.extract(member, path=None, pwd=None)¶
将存档中的成员解压缩到当前工作目录;member 必须是其全名或
ZipInfo
对象。其文件信息将尽可能准确地提取。path 指定要解压缩到的其他目录。member 可以是文件名或ZipInfo
对象。pwd 是用于加密文件的密码,以bytes
对象形式提供。返回创建的规范化路径(目录或新文件)。
注意
如果成员文件名是绝对路径,则驱动器/UNC 共享点和前导(反斜杠)将被删除,例如:
///foo/bar
在 Unix 上变为foo/bar
,而C:\foo\bar
在 Windows 上变为foo\bar
。并且成员文件名中的所有".."
组件都将被删除,例如:../../foo../../ba..r
变为foo../ba..r
。在 Windows 上,非法字符(:
、<
、>
、|
、"
、?
和*
)将替换为下划线(_
)。在 3.6 版更改: 在关闭的 ZipFile 上调用
extract()
将引发ValueError
。以前,会引发RuntimeError
。在 3.6.2 版更改: path 参数接受 类路径对象。
- ZipFile.extractall(path=None, members=None, pwd=None)¶
将存档中的所有成员解压缩到当前工作目录。path 指定要解压缩到的其他目录。members 是可选的,并且必须是
namelist()
返回的列表的子集。pwd 是用于加密文件的密码,以bytes
对象形式提供。警告
切勿在没有事先检查的情况下从不受信任的来源提取存档。文件可能会在 path 之外创建,例如,以
"/"
开头的绝对文件名或包含两个点".."
的文件名。此模块会尝试阻止这种情况。请参阅extract()
说明。在 3.6 版更改: 在关闭的 ZipFile 上调用
extractall()
将引发ValueError
。以前,会引发RuntimeError
。在 3.6.2 版更改: path 参数接受 类路径对象。
- ZipFile.printdir()¶
将存档的内容表打印到
sys.stdout
。
- ZipFile.read(name, pwd=None)¶
返回存档中文件 name 的字节。name 是存档中文件的名称,或
ZipInfo
对象。存档必须以读取或追加模式打开。pwd 是用于加密文件的密码,以bytes
对象形式提供,如果指定,则会覆盖使用setpassword()
设置的默认密码。在使用除ZIP_STORED
、ZIP_DEFLATED
、ZIP_BZIP2
或ZIP_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'
模式打开。注意
ZIP 文件标准历来没有指定元数据编码,但强烈建议使用 CP437(原始 IBM PC 编码)以实现互操作性。最近的版本允许使用 UTF-8(仅限)。在此模块中,如果成员名称包含任何非 ASCII 字符,则将自动使用 UTF-8 来写入它们。无法使用 ASCII 或 UTF-8 以外的任何编码写入成员名称。
注意
存档名称应相对于存档根目录,也就是说,它们不应以路径分隔符开头。
注意
如果
arcname
(或者在未给出arcname
的情况下为filename
)包含空字节,则存档中文件的名称将在空字节处被截断。注意
文件名中的前导斜杠可能会导致存档在 Windows 系统上的某些 zip 程序中无法打开。
3.6 版更改: 在以
'r'
模式创建的 ZipFile 或已关闭的 ZipFile 上调用write()
将引发ValueError
。以前会引发RuntimeError
。
- ZipFile.writestr(zinfo_or_arcname, data, compress_type=None, compresslevel=None)¶
将文件写入存档。内容为 data,它可以是
str
或bytes
实例;如果是str
,则先将其编码为 UTF-8。zinfo_or_arcname 是它在存档中使用的文件名,或者是一个ZipInfo
实例。如果它是一个实例,则至少必须给出文件名、日期和时间。如果它是一个名称,则日期和时间将设置为当前日期和时间。存档必须以'w'
、'x'
或'a'
模式打开。如果给出,则 compress_type 将覆盖为新条目的构造函数的 compression 参数指定的值,或者覆盖 zinfo_or_arcname 中的值(如果它是一个
ZipInfo
实例)。同样,如果给出,则 compresslevel 将覆盖构造函数。注意
当传递一个
ZipInfo
实例作为 zinfo_or_arcname 参数时,使用的压缩方法将是给定ZipInfo
实例的 compress_type 成员中指定的方法。默认情况下,ZipInfo
构造函数将此成员设置为ZIP_STORED
。3.2 版更改: 添加了 compress_type 参数。
3.6 版更改: 在以
'r'
模式创建的 ZipFile 或已关闭的 ZipFile 上调用writestr()
将引发ValueError
。以前会引发RuntimeError
。
- ZipFile.mkdir(zinfo_or_directory, mode=511)¶
在存档内创建一个目录。如果 zinfo_or_directory 是一个字符串,则会在存档内创建一个目录,其模式在 mode 参数中指定。但是,如果 zinfo_or_directory 是一个
ZipInfo
实例,则 mode 参数将被忽略。存档必须以
'w'
、'x'
或'a'
模式打开。3.11 版新增。
以下数据属性也可用
- ZipFile.filename¶
ZIP 文件的名称。
- ZipFile.debug¶
要使用的调试输出级别。可以从
0
(默认值,无输出)设置为3
(最多输出)。调试信息写入sys.stdout
。
路径对象¶
- class zipfile.Path(root, at='')¶
从
root
zip 文件(可以是ZipFile
实例或适合传递给ZipFile
构造函数的file
)构造一个 Path 对象。at
指定此路径在 zip 文件中的位置,例如“dir/file.txt”、“dir/”或“”。默认为空字符串,表示根目录。
Path 对象公开了 pathlib.Path
对象的以下功能
可以使用 /
运算符或 joinpath
遍历路径对象。
- Path.name¶
最终路径组件。
- Path.open(mode='r', *, pwd, **)¶
在当前路径上调用
ZipFile.open()
。允许通过支持的模式进行读取或写入、文本或二进制文件:“r”、“w”、“rb”、“wb”。位置参数和关键字参数在以文本形式打开时传递给io.TextIOWrapper
,否则将被忽略。pwd
是传递给ZipFile.open()
的pwd
参数。在 3.9 版更改: 添加了对 open 的文本和二进制模式的支持。默认模式现在是文本。
在 3.11.2 版更改: 可以将
encoding
参数作为位置参数提供,而不会导致TypeError
。因为它在 3.9 中可以这样做。需要与未修补的 3.10 和 3.11 版本兼容的代码必须将所有io.TextIOWrapper
参数(包括encoding
)作为关键字传递。
- Path.iterdir()¶
枚举当前目录的子项。
- Path.is_dir()¶
如果当前上下文引用目录,则返回
True
。
- Path.is_file()¶
如果当前上下文引用文件,则返回
True
。
- Path.exists()¶
如果当前上下文引用 zip 文件中的文件或目录,则返回
True
。
- Path.suffix¶
最终组件的文件扩展名。
在 3.11 版中添加: 添加了
Path.suffix
属性。
- Path.suffixes¶
路径的文件扩展名列表。
在 3.11 版中添加: 添加了
Path.suffixes
属性。
- Path.read_text(*, **)¶
将当前文件读取为 Unicode 文本。位置参数和关键字参数将传递给
io.TextIOWrapper
(buffer
除外,它由上下文隐含)。在 3.11.2 版更改: 可以将
encoding
参数作为位置参数提供,而不会导致TypeError
。因为它在 3.9 中可以这样做。需要与未修补的 3.10 和 3.11 版本兼容的代码必须将所有io.TextIOWrapper
参数(包括encoding
)作为关键字传递。
- Path.read_bytes()¶
将当前文件读取为字节。
- Path.joinpath(*other)¶
返回一个新的 Path 对象,其中每个 *other* 参数都已连接。以下两种写法是等效的
>>> Path(...).joinpath('child').joinpath('grandchild') >>> Path(...).joinpath('child', 'grandchild') >>> Path(...) / 'child' / 'grandchild'
在 3.10 版更改: 在 3.10 之前,
joinpath
未记录在案,并且只接受一个参数。
zipp 项目为旧版 Python 提供了最新路径对象功能的向后移植。使用 zipp.Path
代替 zipfile.Path
可以尽早访问更改。
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
并将相应文件添加到存档中。如果未给出
PyZipFile
的 optimize 参数或为-1
,则相应文件为*.pyc
文件,必要时进行编译。如果
PyZipFile
的 optimize 参数为0
、1
或2
,则仅将具有该优化级别的文件(请参阅compile()
)添加到存档中,必要时进行编译。如果 pathname 是文件,则文件名必须以
.py
结尾,并且仅在顶级添加(对应的*.pyc
)文件(无路径信息)。如果 pathname 是不以.py
结尾的文件,则会引发RuntimeError
。如果它是一个目录,并且该目录不是包目录,则所有文件*.pyc
都将添加到顶级。如果该目录是包目录,则所有*.pyc
都将作为文件路径添加到包名称下,并且如果有任何子目录是包目录,则所有这些子目录都将按排序顺序递归添加。basename 仅供内部使用。
如果给出 filterfunc,则它必须是一个接受单个字符串参数的函数。在将每个路径(包括每个单独的完整文件路径)添加到存档之前,它将被传递给该函数。如果 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 版更改: 添加了 filterfunc 参数。
在 3.6.2 版更改: pathname 参数接受 类路径对象。
在 3.7 版更改: 递归排序目录条目。
ZipInfo 对象¶
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 版新增。
在 3.6.2 版更改: filename 参数接受 类路径对象。
在 3.8 版更改: 添加了仅限关键字的参数 strict_timestamps。
实例具有以下方法和属性
- ZipInfo.is_dir()¶
如果此存档成员是目录,则返回
True
。这使用条目的名称:目录应始终以
/
结尾。3.6 版新增。
- ZipInfo.filename¶
存档中文件的名称。
- ZipInfo.date_time¶
存档成员上次修改的时间和日期。这是一个由六个值组成的元组
索引
值
0
年份(>= 1980)
1
月份(从 1 开始)
2
日期(从 1 开始)
3
小时(从 0 开始)
4
分钟(从 0 开始)
5
秒(从 0 开始)
注意
ZIP 文件格式不支持 1980 年之前的日期时间戳。
- ZipInfo.compress_type¶
存档成员的压缩类型。
- ZipInfo.extra¶
扩展字段数据。《PKZIP 应用说明》包含对此
bytes
对象中包含的数据的内部结构的一些注释。
- ZipInfo.create_system¶
创建 ZIP 档案的系统。
- ZipInfo.create_version¶
创建 ZIP 档案的 PKZIP 版本。
- 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¶
未压缩文件的大小。
命令行界面¶
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
命令行选项¶
解压缩陷阱¶
由于以下列出的一些陷阱,zipfile 模块中的解压缩可能会失败。
来自文件本身¶
由于密码错误/CRC校验和错误/ZIP格式错误或不支持的压缩方法/解密,解压缩可能会失败。
文件系统限制¶
超过不同文件系统的限制会导致解压缩失败。例如目录条目中允许的字符、文件名长度、路径名长度、单个文件大小和文件数量等。
资源限制¶
缺少内存或磁盘空间会导致解压缩失败。例如,解压缩炸弹(又名 ZIP 炸弹)适用于可能导致磁盘空间耗尽的 zipfile 库。
中断¶
解压缩过程中的中断,例如按 Ctrl+C 或终止解压缩进程,可能会导致档案解压缩不完整。
提取的默认行为¶
不知道默认的提取行为可能会导致意外的解压缩结果。例如,两次提取同一个档案时,它会在不询问的情况下覆盖文件。