12.5. tarfile — 读写 tar 归档文件 — Python 文档

来自菜鸟教程
Python/docs/2.7/library/tarfile
跳转至:导航、​搜索

12.5. tar文件 — 读写 tar 归档文件

2.3 版中的新功能。


源代码: :source:`Lib/tarfile.py`



tarfile 模块可以读取和写入 tar 档案,包括使用 gzip 或 bz2 压缩的档案。 使用 zipfile 模块读取或写入 .zip 文件,或 shutil 中的更高级别函数。

一些事实和数据:

  • 如果相应的模块可用,则读取和写入 gzipbz2 压缩档案。

  • 对 POSIX.1-1988 (ustar) 格式的读/写支持。

  • 对 GNU tar 格式的读/写支持,包括 longnamelonglink 扩展,对 sparse 扩展的只读支持。

  • 对 POSIX.1-2001 (pax) 格式的读/写支持。

    2.6 版中的新功能。

  • 处理目录、常规文件、硬链接、符号链接、fifos、字符设备和块设备,并能够获取和恢复文件信息,如时间戳、访问权限和所有者。

笔记

不支持处理多流 bzip2 文件。 诸如 bz2file 之类的模块可以让您克服这个问题。


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 对象
tarfile.is_tarfile(name)
如果 name 是 tar 存档文件,则返回 Truetarfile 模块可以读取该文件。
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,则用于读取或写入数据。 如果可以确定,则 modefileobj 的模式覆盖。 fileobj 将从位置 0 开始使用。

笔记

fileobj 不关闭,当 TarFile 关闭时。

format 控制存档格式。 它必须是在模块级别定义的常量 USTAR_FORMATGNU_FORMATPAX_FORMAT 之一。

2.6 版中的新功能。

tarinfo 参数可用于用不同的类替换默认的 TarInfo 类。

2.6 版中的新功能。

如果 dereferenceFalse,则将符号链接和硬链接添加到存档。 如果是True,则将目标文件的内容添加到存档中。 这对不支持符号链接的系统没有影响。

如果 ignore_zerosFalse,则将空块视为存档的结尾。 如果是 True,则跳过空(和无效)块并尝试获取尽可能多的成员。 这仅对读取连接或损坏的档案有用。

debug 可以设置为从 0(无调试消息)到 3(所有调试消息)。 消息写入 sys.stderr

如果 errorlevel0,则使用 TarFile.extract() 时会忽略所有错误。 然而,当启用调试时,它们在调试输出中显示为错误消息。 如果是 1,则所有 fatal 错误都会作为 OSErrorIOError 异常引发。 如果 2,所有 非致命 错误也会作为 TarError 异常引发。

encodingerrors 参数控制字符串转换为 unicode 对象的方式,反之亦然。 默认设置适用于大多数用户。 有关详细信息,请参阅 Unicode 问题 部分。

2.6 版中的新功能。

pax_headers 参数是一个可选的 unicode 字符串字典,如果 formatPAX_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。 如果 verboseFalse,则仅打印成员的名称。 如果是 True,则产生类似于 ls -l 的输出。
TarFile.next()
当打开 TarFile 进行读取时,将存档的下一个成员作为 TarInfo 对象返回。 如果没有更多可用,则返回 None
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 指定存档中文件的替代名称,否则,名称取自 fileobjname 属性,或 ]name 参数。

在使用 addfile() 添加之前,您可以修改 TarInfo 的一些属性。 如果文件对象不是位于文件开头的普通文件对象,可能需要修改size等属性。 对于诸如 GzipFile 之类的对象就是这种情况。 name 也可以修改,在这种情况下 arcname 可能是一个虚拟字符串。

TarFile.close()
关闭 TarFile。 在写入模式下,两个完成零块被附加到存档中。
TarFile.posix

将此设置为 True 相当于将 format 属性设置为 USTAR_FORMATFalse 相当于 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.fromtarfile(tarfile)

TarFile 对象 tarfile 读取下一个成员并将其作为 TarInfo 对象返回。

2.6 版中的新功能。

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 通常是以下常量之一:REGTYPEAREGTYPELNKTYPESYMTYPEDIRTYPE、[ X104X]、CONTTYPECHRTYPEBLKTYPEGNUTYPE_SPARSE。 要更方便地确定 TarInfo 对象的类型,请使用下面的 is*() 方法。
TarInfo.linkname
目标文件名的名称,仅存在于 LNKTYPESYMTYPE 类型的 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 类的 encodingerrors 关键字参数控制。

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',以确保名称信息不会被更改而被忽视。