12.5. tarfile — 读写 tar 归档文件 — Python 文档
12.5. tar文件 — 读写 tar 归档文件
2.3 版中的新功能。
tarfile 模块可以读取和写入 tar 档案,包括使用 gzip 或 bz2 压缩的档案。 使用 zipfile 模块读取或写入 .zip
文件,或 shutil 中的更高级别函数。
一些事实和数据:
对 POSIX.1-1988 (ustar) 格式的读/写支持。
对 GNU tar 格式的读/写支持,包括 longname 和 longlink 扩展,对 sparse 扩展的只读支持。
对 POSIX.1-2001 (pax) 格式的读/写支持。
2.6 版中的新功能。
处理目录、常规文件、硬链接、符号链接、fifos、字符设备和块设备,并能够获取和恢复文件信息,如时间戳、访问权限和所有者。
- tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, \*\*kwargs)
为路径名 name 返回一个 TarFile 对象。 有关 TarFile 对象和允许的关键字参数的详细信息,请参阅 TarFile 对象 。
mode 必须是
'filemode[:compression]'
形式的字符串,默认为'r'
。 以下是模式组合的完整列表:模式
行动
'r' or 'r:*'
使用透明压缩打开阅读(推荐)。
'r:'
开放阅读,无需压缩。
'r:gz'
使用 gzip 压缩打开以供阅读。
'r:bz2'
使用 bzip2 压缩打开以供阅读。
'a' or 'a:'
打开以追加,无压缩。 如果文件不存在,则创建该文件。
'w' or 'w:'
打开无压缩写入。
'w:gz'
打开 gzip 压缩写入。
'w:bz2'
为 bzip2 压缩写入打开。
请注意,
'a:gz'
或'a:bz2'
是不可能的。 如果 mode 不适合打开某个(压缩)文件进行读取,则会引发 ReadError。 使用 mode'r'
来避免这种情况。 如果不支持压缩方法,则会引发 CompressionError。如果指定了 fileobj,它将用作为 name 打开的文件对象的替代。 它应该在位置 0。
对于模式
'w:gz'
、'r:gz'
、'w:bz2'
、'r:bz2'
、tarfile.open() 接受关键字参数 compresslevel[ X124X](默认9
)指定文件的压缩级别。出于特殊目的,模式还有第二种格式:
'filemode|[compression]'
。 tarfile.open() 将返回一个 TarFile 对象,该对象将其数据作为块流处理。 不会对文件进行随机搜索。 如果给定,fileobj 可以是任何具有read()
或write()
方法的对象(取决于 mode)。 bufsize 指定块大小,默认为20 * 512
字节。 将此变体与例如结合使用sys.stdin
,套接字文件对象或磁带设备。 然而,这样的 TarFile 对象受到限制,因为它不允许随机访问,请参阅 示例 。 当前可能的模式:模式
行动
*' 打开 tar 块的 流 以使用透明压缩进行读取。
' 打开未压缩的 tar 块的 流 以进行读取。
gz' 打开 gzip 压缩的 stream 进行阅读。
bz2' 打开一个 bzip2 压缩的 stream 进行读取。
' 打开未压缩的 流 进行写入。
gz' 打开一个 gzip 压缩的 stream 进行写入。
bz2' 打开一个 bzip2 压缩的 stream 进行写入。
- class tarfile.TarFile
- 用于读取和写入 tar 档案的类。 不要直接使用这个类,最好使用 tarfile.open() 代替。 参见 TarFile 对象 。
- class tarfile.TarFileCompat(filename, mode='r', compression=TAR_PLAIN)
使用类似 zipfile 的界面对 tar 档案进行有限访问的类。 有关更多详细信息,请参阅 zipfile 模块的文档。 compression 必须是以下常量之一:
- TAR_PLAIN
未压缩 tar 存档的常量。
- TAR_GZIPPED
gzip 压缩 tar 存档的常量。
自 2.6 版起已弃用:TarFileCompat 类已在 Python 3 中删除。
- exception tarfile.TarError
- 所有 tarfile 异常的基类。
- exception tarfile.ReadError
- 在打开 tar 存档时引发,tarfile 模块无法处理或以某种方式无效。
- exception tarfile.CompressionError
- 当不支持压缩方法或无法正确解码数据时引发。
- exception tarfile.StreamError
- 由于流类 TarFile 对象的典型限制而引发。
- exception tarfile.ExtractError
- 使用 TarFile.extract() 时,针对 非致命 错误引发,但仅在
TarFile.errorlevel
== 2
时引发。
以下常量在模块级别可用:
- tarfile.ENCODING
- 默认字符编码:Windows 上的
'utf-8'
,否则为 sys.getfilesystemencoding() 返回的值。
- exception tarfile.HeaderError
如果它获得的缓冲区无效,则由 TarInfo.frombuf() 引发。
2.6 版中的新功能。
以下每个常量定义了 tarfile 模块能够创建的 tar 存档格式。 有关详细信息,请参阅 支持的 tar 格式 部分。
- tarfile.USTAR_FORMAT
- POSIX.1-1988 (ustar) 格式。
- tarfile.GNU_FORMAT
- GNU tar 格式。
- tarfile.PAX_FORMAT
- POSIX.1-2001 (pax) 格式。
- tarfile.DEFAULT_FORMAT
- 创建档案的默认格式。 目前是 GNU_FORMAT。
也可以看看
- 模块 zipfile
- zipfile 标准模块的文档。
- 归档操作
- 标准 shutil 模块提供的更高级别归档工具的文档。
- GNU tar 手册,基本 Tar 格式
- tar 存档文件的文档,包括 GNU tar 扩展。
12.5.1. TarFile 对象
TarFile 对象提供了一个 tar 存档的接口。 tar 档案是一个块序列。 归档成员(存储的文件)由头块和数据块组成。 可以将文件多次存储在 tar 存档中。 每个存档成员都由一个 TarInfo 对象表示,有关详细信息,请参阅 TarInfo 对象 。
TarFile 对象可以用作 with 语句中的上下文管理器。 当块完成时它会自动关闭。 请注意,如果出现异常情况,为写入而打开的存档将不会被最终确定; 只有内部使用的文件对象将被关闭。 有关用例,请参阅 示例 部分。
2.7 新功能: 增加了对上下文管理协议的支持。
- class tarfile.TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors=None, pax_headers=None, debug=0, errorlevel=0)
以下所有参数都是可选的,也可以作为实例属性访问。
name 是存档的路径名。 如果给出 fileobj,则可以省略。 在这种情况下,如果存在文件对象的
name
属性,则使用该属性。mode 是
'r'
从现有档案中读取,'a'
将数据附加到现有文件或'w'
创建新文件覆盖现有文件一。如果给出 fileobj,则用于读取或写入数据。 如果可以确定,则 mode 被 fileobj 的模式覆盖。 fileobj 将从位置 0 开始使用。
笔记
fileobj 不关闭,当 TarFile 关闭时。
format 控制存档格式。 它必须是在模块级别定义的常量 USTAR_FORMAT、GNU_FORMAT 或 PAX_FORMAT 之一。
2.6 版中的新功能。
tarinfo 参数可用于用不同的类替换默认的 TarInfo 类。
2.6 版中的新功能。
如果 dereference 是 False,则将符号链接和硬链接添加到存档。 如果是True,则将目标文件的内容添加到存档中。 这对不支持符号链接的系统没有影响。
如果 ignore_zeros 是 False,则将空块视为存档的结尾。 如果是 True,则跳过空(和无效)块并尝试获取尽可能多的成员。 这仅对读取连接或损坏的档案有用。
debug 可以设置为从
0
(无调试消息)到3
(所有调试消息)。 消息写入sys.stderr
。如果 errorlevel 为
0
,则使用 TarFile.extract() 时会忽略所有错误。 然而,当启用调试时,它们在调试输出中显示为错误消息。 如果是1
,则所有 fatal 错误都会作为OSError
或IOError
异常引发。 如果2
,所有 非致命 错误也会作为 TarError 异常引发。encoding 和 errors 参数控制字符串转换为 unicode 对象的方式,反之亦然。 默认设置适用于大多数用户。 有关详细信息,请参阅 Unicode 问题 部分。
2.6 版中的新功能。
pax_headers 参数是一个可选的 unicode 字符串字典,如果 format 是 PAX_FORMAT,它将作为 pax 全局标头添加。
2.6 版中的新功能。
- classmethod TarFile.open(...)
- 替代构造函数。 tarfile.open() 函数实际上是这个类方法的快捷方式。
- TarFile.getmember(name)
为成员 name 返回一个 TarInfo 对象。 如果在存档中找不到 name,则会引发
KeyError
。笔记
如果某个成员在存档中出现多次,则假定其最后一次出现是最新版本。
- TarFile.getmembers()
- 将存档成员作为 TarInfo 对象列表返回。 该列表与存档中的成员具有相同的顺序。
- TarFile.getnames()
- 将成员作为其姓名列表返回。 它与 getmembers() 返回的列表具有相同的顺序。
- TarFile.list(verbose=True)
- 将目录打印到
sys.stdout
。 如果 verbose 是 False,则仅打印成员的名称。 如果是 True,则产生类似于 ls -l 的输出。
- TarFile.extractall(path='.', members=None)
将存档中的所有成员提取到当前工作目录或目录 path。 如果给出了可选的 members,它必须是由 getmembers() 返回的列表的子集。 在提取所有成员后设置目录信息,如所有者、修改时间和权限。 这样做是为了解决两个问题: 每次在其中创建文件时都会重置目录的修改时间。 而且,如果目录的权限不允许写入,则将文件提取到该目录将失败。
警告
未经事先检查,切勿从不受信任的来源提取档案。 文件可能是在 path 之外创建的,例如 具有以
"/"
开头的绝对文件名或以两个点".."
开头的文件名的成员。2.5 版中的新功能。
- TarFile.extract(member, path=)
使用其全名从存档中提取成员到当前工作目录。 尽可能准确地提取其文件信息。 member 可以是文件名或 TarInfo 对象。 您可以使用 path 指定不同的目录。
笔记
extract() 方法不处理几个提取问题。 在大多数情况下,您应该考虑使用 extractall() 方法。
警告
请参阅 extractall() 的警告。
- TarFile.extractfile(member)
从存档中提取成员作为文件对象。 member 可以是文件名或 TarInfo 对象。 如果 member 是一个普通文件,则返回一个类文件对象。 如果 member 是链接,则从链接的目标构造一个类文件对象。 如果 member 以上都不是,则返回 None。
笔记
类文件对象是只读的。 它提供了方法
read()
、readline()、readlines()
、seek()
、tell()
和 close()[ X104X],并且还支持对其行进行迭代。
- TarFile.add(name, arcname=None, recursive=True, exclude=None, filter=None)
将文件 name 添加到存档中。 name 可以是任何类型的文件(目录、fifo、符号链接等)。 如果给定,arcname 指定存档中文件的替代名称。 默认情况下以递归方式添加目录。 这可以通过将 recursive 设置为 False 来避免。 如果给出 exclude,它必须是一个函数,它接受一个文件名参数并返回一个布尔值。 根据这个值,相应的文件要么被排除(True),要么被添加(False)。 如果指定了 filter,它必须是一个函数,它接受一个 TarInfo 对象参数并返回更改后的 TarInfo 对象。 如果它返回 None,则 TarInfo 对象将从存档中排除。 有关示例,请参阅 示例 。
2.6 版更改: 添加 排除 参数。
2.7 版更改: 添加 过滤器 参数。
自 2.7 版起已弃用:不推荐使用 exclude 参数,请改用 filter 参数。 为了获得最大的可移植性,filter 应该用作关键字参数而不是位置参数,这样在最终删除 exclude 时代码不会受到影响。
- TarFile.addfile(tarinfo, fileobj=None)
将 TarInfo 对象 tarinfo 添加到存档中。 如果给出 fileobj,则从中读取
tarinfo.size
字节并将其添加到存档中。 您可以直接创建 TarInfo 对象,也可以使用 gettarinfo()。笔记
在 Windows 平台上,fileobj 应该总是以
'rb'
模式打开,以避免对文件大小的影响。
- TarFile.gettarinfo(name=None, arcname=None, fileobj=None)
根据现有文件上的 os.stat() 或等效结果创建 TarInfo 对象。 该文件要么由 name 命名,要么指定为具有文件描述符的文件对象 fileobj。 如果给定,arcname 指定存档中文件的替代名称,否则,名称取自 fileobj 的 name 属性,或 ]name 参数。
在使用 addfile() 添加之前,您可以修改 TarInfo 的一些属性。 如果文件对象不是位于文件开头的普通文件对象,可能需要修改size等属性。 对于诸如 GzipFile 之类的对象就是这种情况。 name 也可以修改,在这种情况下 arcname 可能是一个虚拟字符串。
- TarFile.close()
- 关闭 TarFile。 在写入模式下,两个完成零块被附加到存档中。
- TarFile.posix
将此设置为 True 相当于将 format 属性设置为 USTAR_FORMAT,False 相当于 GNU_FORMAT。
2.4 版更改:posix 默认为 False。
自 2.6 版起已弃用: 改用 格式 属性。
- TarFile.pax_headers
包含 pax 全局标头的键值对的字典。
2.6 版中的新功能。
12.5.2. TarInfo 对象
TarInfo 对象代表 TarFile 中的一个成员。 除了存储文件的所有必需属性(如文件类型、大小、时间、权限、所有者等)外,它还提供了一些有用的方法来确定其类型。 它确实 不 包含文件本身的数据。
TarInfo 对象由 TarFile 的方法 getmember()
、getmembers()
和 gettarinfo()
返回。
- class tarfile.TarInfo(name=)
- 创建一个 TarInfo 对象。
- TarInfo.frombuf(buf)
从字符串缓冲区 buf 创建并返回一个 TarInfo 对象。
2.6 版新功能: 引发 HeaderError 如果缓冲区无效..
- TarInfo.tobuf(format=DEFAULT_FORMAT, encoding=ENCODING, errors='strict')
从 TarInfo 对象创建字符串缓冲区。 有关参数的信息,请参阅 TarFile 类的构造函数。
2.6 版更改: 添加了参数。
TarInfo
对象具有以下公共数据属性:
- TarInfo.name
- 存档成员的名称。
- TarInfo.size
- 以字节为单位的大小。
- TarInfo.mtime
- 上次修改时间。
- TarInfo.mode
- 权限位。
- TarInfo.type
- 文件类型。 type 通常是以下常量之一:
REGTYPE
、AREGTYPE
、LNKTYPE
、SYMTYPE
、DIRTYPE
、[ X104X]、CONTTYPE
、CHRTYPE
、BLKTYPE
、GNUTYPE_SPARSE
。 要更方便地确定 TarInfo 对象的类型,请使用下面的is*()
方法。
- TarInfo.linkname
- 目标文件名的名称,仅存在于
LNKTYPE
和SYMTYPE
类型的 TarInfo 对象中。
- TarInfo.uid
- 最初存储此成员的用户的用户 ID。
- TarInfo.gid
- 最初存储此成员的用户的组 ID。
- TarInfo.uname
- 用户名。
- TarInfo.gname
- 团队名字。
- TarInfo.pax_headers
包含关联 pax 扩展标头的键值对的字典。
2.6 版中的新功能。
TarInfo 对象还提供了一些方便的查询方法:
- TarInfo.isfile()
- 如果
Tarinfo
对象是常规文件,则返回 True。
- TarInfo.isreg()
- 与 isfile() 相同。
- TarInfo.isdir()
- 如果是目录,则返回 True。
- TarInfo.issym()
- 如果是符号链接,则返回 True。
- TarInfo.islnk()
- 如果是硬链接,则返回 True。
- TarInfo.ischr()
- 如果是字符设备,则返回 True。
- TarInfo.isblk()
- 如果是块设备,则返回 True。
- TarInfo.isfifo()
- 如果是 FIFO,则返回 True。
- TarInfo.isdev()
- 如果是字符设备、块设备或 FIFO 之一,则返回 True。
12.5.3. 例子
如何将整个 tar 存档解压缩到当前工作目录:
import tarfile
tar = tarfile.open("sample.tar.gz")
tar.extractall()
tar.close()
如何使用生成器函数而不是列表提取带有 TarFile.extractall() 的 tar 存档的子集:
import os
import tarfile
def py_files(members):
for tarinfo in members:
if os.path.splitext(tarinfo.name)[1] == ".py":
yield tarinfo
tar = tarfile.open("sample.tar.gz")
tar.extractall(members=py_files(tar))
tar.close()
如何从文件名列表创建未压缩的 tar 存档:
import tarfile
tar = tarfile.open("sample.tar", "w")
for name in ["foo", "bar", "quux"]:
tar.add(name)
tar.close()
使用 with 语句的相同示例:
import tarfile
with tarfile.open("sample.tar", "w") as tar:
for name in ["foo", "bar", "quux"]:
tar.add(name)
如何读取 gzip 压缩的 tar 存档并显示一些成员信息:
import tarfile
tar = tarfile.open("sample.tar.gz", "r:gz")
for tarinfo in tar:
print tarinfo.name, "is", tarinfo.size, "bytes in size and is",
if tarinfo.isreg():
print "a regular file."
elif tarinfo.isdir():
print "a directory."
else:
print "something else."
tar.close()
如何使用 TarFile.add() 中的 filter 参数创建存档和重置用户信息:
import tarfile
def reset(tarinfo):
tarinfo.uid = tarinfo.gid = 0
tarinfo.uname = tarinfo.gname = "root"
return tarinfo
tar = tarfile.open("sample.tar.gz", "w:gz")
tar.add("foo", filter=reset)
tar.close()
12.5.4. 支持的 tar 格式
可以使用 tarfile 模块创建三种 tar 格式:
POSIX.1-1988 ustar 格式 (USTAR_FORMAT)。 它支持最多 256 个字符的文件名和最多 100 个字符的链接名。 最大文件大小为 8 GB。 这是一种古老而有限但得到广泛支持的格式。
GNU tar 格式 (GNU_FORMAT)。 它支持长文件名和链接名、大于 8 GB 的文件和稀疏文件。 它是 GNU/Linux 系统上的事实标准。 tarfile 完全支持长名称的 GNU tar 扩展,稀疏文件支持是只读的。
POSIX.1-2001 pax 格式 (PAX_FORMAT)。 它是最灵活的格式,几乎没有限制。 它支持长文件名和链接名、大文件并以可移植的方式存储路径名。 但是,今天并非所有 tar 实现都能够正确处理 pax 档案。
pax 格式是现有 ustar 格式的扩展。 它对无法以其他方式存储的信息使用额外的标头。 pax 头有两种风格:扩展头仅影响后续文件头,全局头对完整存档有效并影响所有后续文件。 出于可移植性的原因,pax 标头中的所有数据都以 UTF-8 编码。
还有一些 tar 格式的变体可以读取,但不能创建:
- 古老的 V7 格式。 这是 Unix 第七版的第一个 tar 格式,仅存储常规文件和目录。 名称不得超过 100 个字符,没有用户/组名称信息。 如果字段包含非 ASCII 字符,某些存档会错误计算标头校验和。
- SunOS tar 扩展格式。 此格式是 POSIX.1-2001 pax 格式的变体,但不兼容。
12.5.5. Unicode 问题
tar 格式最初的构想是在磁带驱动器上进行备份,主要侧重于保留文件系统信息。 如今,tar 档案通常用于文件分发和通过网络交换档案。 原始格式(所有其他格式只是其变体)的一个问题是没有支持不同字符编码的概念。 例如,在 UTF-8 系统上创建的普通 tar 存档如果包含非 ASCII 字符,则无法在 Latin-1 系统上正确读取。 名称(即 包含这些字符的文件名、链接名、用户/组名)将出现损坏。 不幸的是,没有办法自动检测档案的编码。
pax 格式旨在解决这个问题。 它使用通用字符编码 UTF-8 存储非 ASCII 名称。 读取 pax 存档时,这些 UTF-8 名称将转换为本地文件系统的编码。
unicode 转换的细节由 TarFile 类的 encoding 和 errors 关键字参数控制。
encoding 的默认值是本地字符编码。 它是从 sys.getfilesystemencoding() 和 sys.getdefaultencoding() 推导出来的。 在读取模式下,encoding 专门用于将 unicode 名称从 pax 存档转换为本地字符编码的字符串。 在写入模式下,encoding 的使用取决于所选的存档格式。 对于 PAX_FORMAT,包含非 ASCII 字符的输入名称需要在存储为 UTF-8 字符串之前进行解码。 除非使用 unicode 对象作为输入名称,否则其他格式不使用 encoding。 在将它们添加到存档之前,它们会被转换为 8 位字符串。
errors 参数定义了如何处理无法转换为 encoding 或从 encoding 转换的字符。 Codec Base Classes 部分列出了可能的值。 在读取模式下,有一个额外的方案 'utf-8'
这意味着坏字符被它们的 UTF-8 表示替换。 这是默认方案。 在写入模式下,errors 的默认值为 'strict'
,以确保名称信息不会被更改而被忽视。