Skip to main content

13.6. tarfile —读写tar归档文件

源代码: Lib/tarfile.py


tarfile 模块使得可以读取和写入tar归档,包括使用gzip,bz2和lzma压缩的归档。使用 zipfile 模块读取或写入 .zip 文件或 shutil 中的更高级功能。

一些事实和数字:

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

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

  • 对包括 longnamelonglink 扩展的GNU tar格式的读/写支持,对 sparse 扩展的所有变体的只读支持,包括稀疏文件的恢复。

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

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

在 3.3 版更改: 增加了对 lzma 压缩的支持。

tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)

返回路径名为 nameTarFile 对象。有关允许的 TarFile 对象和关键字参数的详细信息,请参见 TarFile对象

mode 必须是 'filemode[:compression]' 形式的字符串,默认为 'r'。这里是模式组合的完整列表:

模式

行动

'r' or 'r:*'

通过透明压缩打开阅读(推荐)。

'r:'

无压缩打开专用读取。

'r:gz'

使用gzip压缩打开阅读。

'r:bz2'

使用bzip2压缩打开阅读。

'r:xz'

使用lzma压缩打开阅读。

'x''x:'

完全无压缩地创建tarfile。如果 FileExistsError 异常已存在,请提出异常。

'x:gz'

使用gzip压缩创建tarfile。如果 FileExistsError 异常已存在,请提出异常。

'x:bz2'

使用bzip2压缩创建tarfile。如果 FileExistsError 异常已存在,请提出异常。

'x:xz'

使用lzma压缩创建tarfile。如果 FileExistsError 异常已存在,请提出异常。

'a' or 'a:'

打开,无需压缩。如果文件不存在,则创建该文件。

'w' or 'w:'

打开未压缩的写入。

'w:gz'

打开gzip压缩写入。

'w:bz2'

打开bzip2压缩写。

'w:xz'

打开lzma压缩写。

注意,'a:gz''a:bz2''a:xz' 是不可能的。如果 mode 不适合打开某个(压缩)文件进行读取,则会引发 ReadError。使用 mode 'r' 来避免这种情况。如果不支持压缩方法,则会引发 CompressionError

如果指定 fileobj,它将用作 name 以二进制模式打开的 file object 的替代。它应该在位置0。

对于模式 'w:gz''r:gz''w:bz2''r:bz2''x:gz''x:bz2'tarfile.open() 接受关键字参数 compresslevel (缺省 9)以指定文件的压缩级别。

出于特殊目的,mode 有第二种格式:'filemode|[compression]'tarfile.open() 将返回一个 TarFile 对象,它将其数据作为一个块流处理。不会对文件进行随机搜索。如果给出,则 fileobj 可以是具有 read()write() 方法(取决于 mode)的任何对象。 bufsize 指定块大小,默认为 20 * 512 字节。使用此变体与例如 sys.stdin,插座 file object 或磁带设备。然而,这样的 TarFile 对象受限于它不允许随机访问,参见 例子。当前可能的模式:

模式

行动

'r|*'

打开一个用于透明压缩读取的tar块的 stream

'r|'

打开一个未压缩的tar块的 stream 进行读取。

'r|gz'

打开gzip压缩的 stream 进行阅读。

'r|bz2'

打开bzip2压缩的 stream 进行阅读。

'r|xz'

打开lzma压缩的 stream 进行读取。

'w|'

打开未压缩的 stream 进行写入。

'w|gz'

打开gzip压缩的 stream 进行写入。

'w|bz2'

打开bzip2压缩的 stream 进行写入。

'w|xz'

打开lzma压缩的 stream 进行写入。

在 3.5 版更改: 添加了 'x' (独占创建)模式。

class tarfile.TarFile

读写tar存档的类。不要直接使用这个类:使用 tarfile.open()。见 TarFile对象

tarfile.is_tarfile(name)

如果 name 是tar归档文件,则返回 Truetarfile 模块可以读取。

tarfile 模块定义了以下例外:

exception tarfile.TarError

所有 tarfile 异常的基类。

exception tarfile.ReadError

在tar文件打开时引发,无法由 tarfile 模块处理,或者无论如何无效。

exception tarfile.CompressionError

当不支持压缩方法或无法正确解码数据时引发。

exception tarfile.StreamError

对于典型的流式 TarFile 对象的限制而引发。

exception tarfile.ExtractError

在使用 TarFile.extract() 时会引发 non-fatal 错误,但仅在 TarFile.errorlevel == 2 时引发。

exception tarfile.HeaderError

如果 TarInfo.frombuf() 获取的缓冲区无效,则由 TarInfo.frombuf() 引发。

以下常量在模块级可用:

tarfile.ENCODING

默认字符编码:'utf-8' 在Windows上,否则返回 sys.getfilesystemencoding() 的值。

以下每个常量定义 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扩展。

13.6.1. TarFile对象

TarFile 对象提供到tar存档的接口。 tar归档是一系列块。存档成员(存储文件)由标题块,后跟数据块组成。可以将文件存储在tar存档中多次。每个存档成员都由 TarInfo 对象表示,有关详细信息,请参阅 TarInfo对象

TarFile 对象可以用作 with 语句中的上下文管理器。当块完成时,它将自动关闭。请注意,如果出现例外情况,打开写作的存档将不会最终确定;只有内部使用的文件对象将被关闭。有关用例,请参阅 例子 部分。

3.2 新版功能: 增加了对上下文管理协议的支持。

class tarfile.TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors='surrogateescape', pax_headers=None, debug=0, errorlevel=0)

所有以下参数是可选的,并且可以作为实例属性访问。

name 是归档的路径名。如果给出 fileobj,可以省略。在这种情况下,如果文件对象的 name 属性存在,则使用它。

mode 是从现有归档读取的 'r',将数据附加到现有文件的 'a',创建覆盖现有文件的新文件的 'w',或者仅在 'x' 尚不存在的情况下创建新文件。

如果给出 fileobj,它用于读取或写入数据。如果可以确定,mode 将被 fileobj 的模式覆盖。 fileobj 将从位置0开始使用。

注解

TarFile 关闭时,fileobj 不关闭。

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

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

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

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

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

如果 errorlevel0,则使用 TarFile.extract() 时将忽略所有错误。但是,当调试启用时,它们在调试输出中显示为错误消息。如果 1,所有 fatal 错误都作为 OSError 异常引发。如果 2,所有 non-fatal 错误也提升为 TarError 异常。

encodingerrors 参数定义要用于读取或写入归档的字符编码以及如何处理转换错误。默认设置适用于大多数用户。有关详细信息,请参阅 Unicode问题 部分。

pax_headers 参数是字符串的可选字典,如果 formatPAX_FORMAT,则字符串将添加为pax全局头。

在 3.2 版更改: 使用 'surrogateescape' 作为 errors 参数的默认值。

在 3.5 版更改: 添加了 'x' (独占创建)模式。

classmethod TarFile.open(...)

替代构造函数。 tarfile.open() 函数实际上是此类方法的快捷方式。

TarFile.getmember(name)

返回成员 nameTarInfo 对象。如果在归档中找不到 name,则引发 KeyError

注解

如果成员在归档中出现多次,则其最后一次出现被假定为最新的版本。

TarFile.getmembers()

将归档的成员作为 TarInfo 对象的列表返回。该列表与存档中的成员具有相同的顺序。

TarFile.getnames()

返回成员作为他们的名字的列表。它与 getmembers() 返回的列表具有相同的顺序。

TarFile.list(verbose=True, *, members=None)

打印目录到 sys.stdout。如果 verboseFalse,则只打印成员的名称。如果是 True,则产生与 ls -l 类似的输出。如果给出可选的 members,它必须是 getmembers() 返回的列表的子集。

在 3.5 版更改: 添加了 members 参数。

TarFile.next()

当打开 TarFile 进行读取时,将归档的下一个成员作为 TarInfo 对象返回。如果没有更多可用,返回 None

TarFile.extractall(path=".", members=None, *, numeric_owner=False)

将归档中的所有成员解压缩到当前工作目录或目录 path。如果给出了可选的 members,它必须是 getmembers() 返回的列表的子集。在提取所有成员后,设置所有者,修改时间和权限等目录信息。这是为了解决两个问题:目录的修改时间每次在其中创建文件时重置。并且,如果目录的权限不允许写入,则解压缩文件将失败。

如果 numeric_ownerTrue,来自tarfile的uid和gid数字用于设置提取的文件的所有者/组。否则,使用来自tarfile的命名值。

警告

切勿在未经预先检查的情况下从不受信任的来源中提取存档。有可能在 path 之外创建文件,例如。具有以 "/" 开头的绝对文件名或具有两个点 ".." 的文件名的成员。

在 3.5 版更改: 添加了 numeric_owner 参数。

TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False)

使用其全名将成员从归档提取到当前工作目录。其文件信息尽可能精确地提取。 member 可以是文件名或 TarInfo 对象。您可以使用 path 指定其他目录。除非 set_attrs 为假,否则设置文件属性(所有者,mtime,模式)。

如果 numeric_ownerTrue,来自tarfile的uid和gid数字用于设置提取的文件的所有者/组。否则,使用来自tarfile的命名值。

注解

extract() 方法不处理几个提取问题。在大多数情况下,您应该考虑使用 extractall() 方法。

警告

请参阅 extractall() 的警告。

在 3.2 版更改: 添加了 set_attrs 参数。

在 3.5 版更改: 添加了 numeric_owner 参数。

TarFile.extractfile(member)

从存档中提取成员作为文件对象。 member 可以是文件名或 TarInfo 对象。如果 member 是常规文件或链接,则返回 io.BufferedReader 对象。否则,返回 None

在 3.3 版更改: 返回 io.BufferedReader 对象。

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 对象将从归档中排除。参见 例子 的例子。

在 3.2 版更改: 添加了 filter 参数。

3.2 版后已移除: exclude 参数已弃用,请改用 filter 参数。

TarFile.addfile(tarinfo, fileobj=None)

TarInfo 对象 tarinfo 添加到归档。如果给出了 fileobj,它应该是一个 binary file,并从中读取 tarinfo.size 字节并将其添加到归档中。您可以直接创建 TarInfo 对象,也可以使用 gettarinfo()

TarFile.gettarinfo(name=None, arcname=None, fileobj=None)

从现有文件中的 os.stat() 或等效结果创建 TarInfo 对象。该文件由 name 命名,或者指定为具有文件描述符的 file object fileobj。如果给定,arcname 指定档案中文件的备用名称,否则,该名称取自 fileobjname 属性或 name 参数。名称应为文本字符串。

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

TarFile.close()

关闭 TarFile。在写入模式下,两个完成零块附加到归档。

TarFile.pax_headers

包含pax全局头的键/值对的字典。

13.6.2. TarInfo对象

TarInfo 对象表示 TarFile 中的一个成员。除了存储文件的所有必需属性(如文件类型,大小,时间,权限,所有者等),它提供了一些有用的方法来确定它的类型。它 not 包含文件的数据本身。

TarInfo 对象由 TarFile 的方法 getmember()getmembers()gettarinfo() 返回。

class tarfile.TarInfo(name="")

创建 TarInfo 对象。

classmethod TarInfo.frombuf(buf, encoding, errors)

从字符串缓冲区 buf 创建并返回 TarInfo 对象。

如果缓冲区无效,则提升 HeaderError

classmethod TarInfo.fromtarfile(tarfile)

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

TarInfo.tobuf(format=DEFAULT_FORMAT, encoding=ENCODING, errors='surrogateescape')

TarInfo 对象创建字符串缓冲区。有关参数的信息,请参阅 TarFile 类的构造函数。

在 3.2 版更改: 使用 'surrogateescape' 作为 errors 参数的默认值。

TarInfo 对象具有以下公共数据属性:

TarInfo.name

存档成员的名称。

TarInfo.size

大小(以字节为单位)。

TarInfo.mtime

上次修改时间。

TarInfo.mode

权限位。

TarInfo.type

文件类型。 type 通常是这些常数之一:REGTYPEAREGTYPELNKTYPESYMTYPEDIRTYPEFIFOTYPECONTTYPECHRTYPEBLKTYPEGNUTYPE_SPARSE。要更方便地确定 TarInfo 对象的类型,请使用下面的 is*() 方法。

TarInfo.linkname

目标文件名的名称,它只存在于 LNKTYPESYMTYPE 类型的 TarInfo 对象中。

TarInfo.uid

最初存储此成员的用户的用户标识。

TarInfo.gid

最初存储此成员的用户的组ID。

TarInfo.uname

用户名。

TarInfo.gname

组名称。

TarInfo.pax_headers

包含关联的pax扩展头的键值对的字典。

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

13.6.3. 命令行界面

3.4 新版功能.

tarfile 模块提供了一个简单的命令行界面来与tar归档进行交互。

如果要创建新的tar存档,请在 -c 选项后指定其名称,然后列出应包括的文件名:

$ python -m tarfile -c monty.tar  spam.txt eggs.txt

传递目录也是可以接受的:

$ python -m tarfile -c monty.tar life-of-brian_1979/

如果要将tar归档文件解压缩到当前目录中,请使用 -e 选项:

$ python -m tarfile -e monty.tar

您还可以通过传递目录的名称将tar归档文件解压缩到其他目录中:

$ python -m tarfile -e monty.tar  other-dir/

有关tar归档文件中的文件列表,请使用 -l 选项:

$ python -m tarfile -l monty.tar

13.6.3.1. 命令行选项

-l <tarfile>
--list <tarfile>

列出tar文件中的文件。

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

从源文件创建tarfile。

-e <tarfile> [<output_dir>]
--extract <tarfile> [<output_dir>]

如果未指定 output_dir,请将tarfile提取到当前目录中。

-t <tarfile>
--test <tarfile>

测试tarfile是否有效。

-v, --verbose

详细输出。

13.6.4. 例子

如何将整个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", end="")
    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()

13.6.5. 支持的tar格式

可以使用 tarfile 模块创建三种tar格式:

  • POSIX.1-1988 ustar格式(USTAR_FORMAT)。它支持的文件名长度最多为256个字符,链接名称最多为100个字符。最大文件大小为8 GiB。这是一个旧的和有限但广泛支持的格式。

  • GNU tar格式(GNU_FORMAT)。它支持长文件名和链接名,大于8 GiB的文件和稀疏文件。它是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格式的变体,但不兼容。

13.6.6. Unicode问题

tar格式最初是为了在磁带驱动器上进行备份,主要侧重于保留文件系统信息。现在tar存档通常用于文件分发和通过网络交换档案。原始格式(这是所有其他格式的基础)的一个问题是没有支持不同字符编码的概念。例如,如果 UTF-8 系统上创建的普通tar存档包含非 ASCII 字符,则无法在 Latin-1 系统上正确读取。文本元数据(如文件名,链接名,用户/组名称)将显示已损坏。不幸的是,没有办法自动检测归档的编码。 pax格式被设计来解决这个问题。它使用通用字符编码 UTF-8 存储非ASCII元数据。

tarfile 中的字符转换的细节由 TarFile 类的 encodingerrors 关键字参数控制。

encoding 定义要用于存档中元数据的字符编码。默认值为 sys.getfilesystemencoding()'ascii' 作为回退。根据归档是读还是写,元数据必须解码或编码。如果未正确设置 encoding,则此转换可能会失败。

errors 参数定义如何处理无法转换的字符。可能的值列在节 错误处理程序 中。默认方案是 'surrogateescape',Python也用于其文件系统调用,请参见 文件名,命令行参数和环境变量

PAX_FORMAT 存档的情况下,通常不需要 encoding,因为所有元数据都使用 UTF-8 存储。 encoding 仅在极少数情况下用于解码二进制pax头或存储具有替代字符的字符串时使用。