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部分中描述了这些字段。
- class *
-
zipfile.
is_zipfile
(* filename *)- 如果* filename *是基于其幻数的有效 ZIP 文件,则返回
True
,否则返回False
。 文件名也可以是文件或类似文件的对象。
- 如果* filename *是基于其幻数的有效 ZIP 文件,则返回
在版本 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
-
ZIP 文件格式的文档,作者是 Phil Katz,他是该格式和算法的创建者。
-
有关 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的路径。
- class *
-
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 会创建一个 ZIP 文件,当 zipfile 大于 4 GiB 时,将使用 ZIP64extensions。如果是false
,则zipfile将引发异常,当 ZIP 文件需要 ZIP64extensions 时。
-
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 的文件,也会发生类似的行为,时间戳也设置为限制。
如果在模式'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 中进行了更改:添加了对bzip2和lzma压缩的支持。
在版本 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 *) -
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 文件的密码。
- 以类似于二进制文件的对象的形式访问存档的成员。 * name *可以是存档中文件的名称,也可以是ZipInfo对象。 * mode *参数(如果包含)必须为
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 *参数。
在版本 3.6 中更改:删除了对mode='U'
的支持。使用io.TextIOWrapper以universal newlines模式读取压缩的文本文件。
在 3.6 版中进行了更改:open()现在可用于passmode='w'
选项将文件写入存档。
在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用open()将引发ValueError。以前,提出了RuntimeError。
ZipFile.
extract
(* member , path = None , pwd = None *)
返回创建的规范化路径(目录或新文件)。
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_STORED,ZIP_DEFLATED,ZIP_BZIP2或ZIP_LZMA以外的压缩方法的 ZipFile 上调用read()将引发NotImplementedError。如果相应的压缩模块不可用,也会引发错误。
在版本 3.6 中进行了更改:在关闭的 ZipFile 上调用read()将引发ValueError。以前,提出了RuntimeError。
ZipFile.
testzip
( )- 读取存档中的所有文件,并检查其 CRC 和文件头。返回第一个错误文件的名称,否则返回
None
。
- 读取存档中的所有文件,并检查其 CRC 和文件头。返回第一个错误文件的名称,否则返回
在版本 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'
模式打开。
- 将名为* filename 的文件写入存档,并为其指定存档名称 arcname (默认情况下,该名称与 filename 相同,但不带驱动器号,并且删除前导路径分隔符)。如果给定, compress_type 将为新条目的构造函数覆盖为 compression 参数指定的值。同样,如果指定, compresslevel *将覆盖构造函数。存档必须以
Note
存档名称应相对于存档根目录,即,它们不应以路径分隔符开头。
Note
如果arcname
(或filename
,如果未提供arcname
)包含一个空字节,则存档中文件的名称将在该空字节处被截断。
在版本 3.6 中进行了更改:在以'r'
模式创建的 ZipFile 或关闭的 ZipFile 上调用write()将引发ValueError。以前,提出了RuntimeError。
ZipFile.
writestr
(* zinfo_or_arcname , data , compress_type = None , compresslevel = None *)
如果给定,* 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
Path Objects
at
指定此路径在 zip 文件中的位置,例如'dir/file.txt','dir /'或''。默认为空字符串,表示根。
路径对象公开了pathlib.Path个对象的以下Function:
路径对象可使用/
运算符遍历。
-
Path.
name
- finally路径组件。
-
Path.
open
( * , ** )- 在当前路径上调用ZipFile.open()。接受与ZipFile.open()相同的参数。
Caution
此函数的签名在 Python 3.9 中以不兼容的方式更改。对于将来兼容的版本,请考虑使用第三方 zipp.Path 软件包(3.0 或更高版本)。
-
Path.
iterdir
( )- 枚举当前目录的子级。
-
Path.
is_dir
( )- 如果当前上下文引用目录,则返回
True
。
- 如果当前上下文引用目录,则返回
-
Path.
is_file
( )- 如果当前上下文引用文件,则返回
True
。
- 如果当前上下文引用文件,则返回
-
Path.
exists
( )- 如果当前上下文引用了 zip 文件中的文件或目录,则返回
True
。
- 如果当前上下文引用了 zip 文件中的文件或目录,则返回
-
Path.
read_text
( * , ** )- 以 unicode 文本读取当前文件。位置参数和关键字参数传递给io.TextIOWrapper(上下文所隐含的
buffer
除外)。
- 以 unicode 文本读取当前文件。位置参数和关键字参数传递给io.TextIOWrapper(上下文所隐含的
-
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 *参数。
- class *
在版本 3.4 中更改:默认情况下启用 ZIP64 扩展。
实例除ZipFile对象之外,还有一种方法:
writepy
(* pathname , basename ='', filterfunc = None *)- 搜索文件
*.py
并将相应的文件添加到存档中。
- 搜索文件
如果未提供PyZipFile或-1
的* optimize *参数,则对应的文件是*.pyc
文件,并在必要时进行编译。
如果PyZipFile的* optimize *参数是0
,1
或2
,则仅将具有该优化级别(请参见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 文件中。
- classmethod *
- 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:
Index | Value |
---|---|
0 | 年(> = 1980) |
1 | Month (one-based) |
2 | 一个月中的某天(基于 1 天) |
3 | Hours (zero-based) |
4 | Minutes (zero-based) |
5 | Seconds (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 或终止解压缩过程)可能会导致存档的解压缩不完全。
提取的默认行为
不知道默认的提取行为会导致意外的减压结果。例如,两次提取相同的归档文件时,它将覆盖文件而无需询问。