12.5. tarfile — 读写tar归档文件

2.3 新版功能.

源代码: Lib/tarfile.py


The tarfile module makes it possible to read and write tar archives, including those using gzip or bz2 compression. Use the zipfile module to read or write .zip files, or the higher-level functions in shutil.

一些事实和数字:

  • reads and writes gzip and bz2 compressed archives if the respective modules are available.

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

  • read/write support for the GNU tar format including longname and longlink extensions, read-only support for the sparse extension.

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

    2.6 新版功能.

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

注解

Handling of multi-stream bzip2 files is not supported. Modules such as bz2file let you overcome this.

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

针对路径名 name 返回 TarFile 对象。 有关 TarFile 对象以及所允许的关键字参数的详细信息请参阅 TarFile 对象

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

模式

action

'r' or 'r:*'

打开和读取使用透明压缩(推荐)。

'r:'

打开和读取不使用压缩。

'r:gz'

打开和读取使用gzip 压缩。

'r:bz2'

打开和读取使用bzip2 压缩。

'a' or 'a:'

打开以便在没有压缩的情况下追加。如果文件不存在,则创建该文件。

'w' or 'w:'

打开用于未压缩的写入。

'w:gz'

打开用于 gzip 压缩的写入。

'w:bz2'

打开用于 bzip2 压缩的写入。

Note that 'a:gz' or 'a:bz2' is not possible. If mode is not suitable to open a certain (compressed) file for reading, ReadError is raised. Use mode 'r' to avoid this. If a compression method is not supported, CompressionError is raised.

If fileobj is specified, it is used as an alternative to a file object opened for name. It is supposed to be at position 0.

For modes 'w:gz', 'r:gz', 'w:bz2', 'r:bz2', tarfile.open() accepts the keyword argument compresslevel (default 9) to specify the compression level of the file.

For special purposes, there is a second format for mode: 'filemode|[compression]'. tarfile.open() will return a TarFile object that processes its data as a stream of blocks. No random seeking will be done on the file. If given, fileobj may be any object that has a read() or write() method (depending on the mode). bufsize specifies the blocksize and defaults to 20 * 512 bytes. Use this variant in combination with e.g. sys.stdin, a socket file object or a tape device. However, such a TarFile object is limited in that it does not allow random access, see 例子. The currently possible modes:

模式

动作

'r|*'

打开 tar 块的 以进行透明压缩读取。

'r|'

打开一个未压缩的 tar 块的 stream 用于读取。

'r|gz'

打开一个 gzip 压缩的 stream 用于读取。

'r|bz2'

打开一个 bzip2 压缩的 stream 用于读取。

'w|'

打开一个未压缩的 stream 用于写入。

'w|gz'

打开一个 gzip 压缩的 stream 用于写入。

'w|bz2'

打开一个 bzip2 压缩的 stream 用于写入。

class tarfile.TarFile

Class for reading and writing tar archives. Do not use this class directly, better use tarfile.open() instead. See TarFile 对象.

tarfile.is_tarfile(name)

如果 name 是一个 tarfile 模块能读取的 tar 归档文件则返回 True

class tarfile.TarFileCompat(filename, mode='r', compression=TAR_PLAIN)

Class for limited access to tar archives with a zipfile-like interface. Please consult the documentation of the zipfile module for more details. compression must be one of the following constants:

TAR_PLAIN

Constant for an uncompressed tar archive.

TAR_GZIPPED

Constant for a gzip compressed tar archive.

2.6 版后已移除: The TarFileCompat class has been removed in Python 3.

exception tarfile.TarError

所有 tarfile 异常的基类。

exception tarfile.ReadError

当一个不能被 tarfile 模块处理或者因某种原因而无效的 tar 归档被打开时将被引发。

exception tarfile.CompressionError

当一个压缩方法不受支持或者当数据无法被正确解码时将被引发。

exception tarfile.StreamError

当达到流式 TarFile 对象的典型限制时将被引发。

exception tarfile.ExtractError

当使用 TarFile.extract() 时针对 non-fatal 所引发的异常,但是仅限 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 manual, Basic Tar Format

针对 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 is the pathname of the archive. It can be omitted if fileobj is given. In this case, the file object’s name attribute is used if it exists.

mode is either 'r' to read from an existing archive, 'a' to append data to an existing file or 'w' to create a new file overwriting an existing one.

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

注解

TarFile 被关闭时,fileobj 不会被关闭。

format 控制归档格式。 它必须为在模块层级定义的常量 USTAR_FORMAT, GNU_FORMATPAX_FORMAT 中的一个。

2.6 新版功能.

tarinfo 参数可以被用来将默认的 TarInfo 类替换为另一个。

2.6 新版功能.

如果 dereferenceFalse,则会将符号链接和硬链接添加到归档中。 如果为 True,则会将目标文件的内容添加到归档中。 在不支持符号链接的系统上参数将不起作用。

如果 ignore_zerosFalse,则会将空的数据块当作归档的末尾来处理。 如果为 True,则会跳过空的(和无效的)数据块并尝试获取尽可能多的成员。 此参数仅适用于读取拼接的或损坏的归档。

debug 可设为从 0 (无调试消息) 到 3 (全部调试消息)。 消息会被写入到 sys.stderr

If errorlevel is 0, all errors are ignored when using TarFile.extract(). Nevertheless, they appear as error messages in the debug output, when debugging is enabled. If 1, all fatal errors are raised as OSError or IOError exceptions. If 2, all non-fatal errors are raised as TarError exceptions as well.

The encoding and errors arguments control the way strings are converted to unicode objects and vice versa. The default settings will work for most users. See section Unicode 问题 for in-depth information.

2.6 新版功能.

The pax_headers argument is an optional dictionary of unicode strings which will be added as a pax global header if format is PAX_FORMAT.

2.6 新版功能.

classmethod TarFile.open(...)

作为替代的构造器。 tarfile.open() 函数实际上是这个类方法的快捷方式。

TarFile.getmember(name)

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

注解

如果一个成员在归档中出现超过一次,它的最后一次出现会被视为是最新的版本。

TarFile.getmembers()

TarInfo 对象列表的形式返回归档的成员。 列表的顺序与归档中成员的顺序一致。

TarFile.getnames()

以名称列表的形式返回成员。 它的顺序与 getmembers() 所返回列表的顺序一致。

TarFile.list(verbose=True)

Print a table of contents to sys.stdout. If verbose is False, only the names of the members are printed. If it is True, output similar to that of ls -l is produced.

TarFile.next()

TarFile 被打开用于读取时,以 TarInfo 对象的形式返回归档的下一个成员。 如果不再有可用对象则返回 None

TarFile.extractall(path=".", members=None)

将归档中的所有成员提取到当前工作目录或 path 目录。 如果给定了可选的 members,则它必须为 getmembers() 所返回的列表的一个子集。 字典信息例如所有者、修改时间和权限会在所有成员提取完毕后被设置。 这样做是为了避免两个问题:目录的修改时间会在每当在其中创建文件时被重置。 并且如果目录的权限不允许写入,提取文件到目录的操作将失败。

警告

绝不要未经预先检验就从不可靠的源中提取归档文件。 这样有可能在 path 之外创建文件,例如某些成员具有以 "/" 开始的绝对路径文件名或带有两个点号 ".." 的文件名。

2.5 新版功能.

TarFile.extract(member, path="")

Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. member may be a filename or a TarInfo object. You can specify a different directory using path.

注解

extract() 方法不会处理某些提取问题。 在大多数情况下你应当考虑使用 extractall() 方法。

警告

参看 extractall() 的警告信息。

TarFile.extractfile(member)

Extract a member from the archive as a file object. member may be a filename or a TarInfo object. If member is a regular file, a file-like object is returned. If member is a link, a file-like object is constructed from the link’s target. If member is none of the above, None is returned.

注解

The file-like object is read-only. It provides the methods read(), readline(), readlines(), seek(), tell(), and close(), and also supports iteration over its lines.

TarFile.add(name, arcname=None, recursive=True, exclude=None, filter=None)

Add the file name to the archive. name may be any type of file (directory, fifo, symbolic link, etc.). If given, arcname specifies an alternative name for the file in the archive. Directories are added recursively by default. This can be avoided by setting recursive to False. If exclude is given it must be a function that takes one filename argument and returns a boolean value. Depending on this value the respective file is either excluded (True) or added (False). If filter is specified it must be a function that takes a TarInfo object argument and returns the changed TarInfo object. If it instead returns None the TarInfo object will be excluded from the archive. See 例子 for an example.

在 2.6 版更改: Added the exclude parameter.

在 2.7 版更改: 添加了 filter 形参。

2.7 版后已移除: The exclude parameter is deprecated, please use the filter parameter instead. For maximum portability, filter should be used as a keyword argument rather than as a positional argument so that code won’t be affected when exclude is ultimately removed.

TarFile.addfile(tarinfo, fileobj=None)

Add the TarInfo object tarinfo to the archive. If fileobj is given, tarinfo.size bytes are read from it and added to the archive. You can create TarInfo objects directly, or by using gettarinfo().

注解

On Windows platforms, fileobj should always be opened with mode 'rb' to avoid irritation about the file size.

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

Create a TarInfo object from the result of os.stat() or equivalent on an existing file. The file is either named by name, or specified as a file object fileobj with a file descriptor. If given, arcname specifies an alternative name for the file in the archive, otherwise, the name is taken from fileobj’s name attribute, or the name argument.

你可以在使用 addfile() 添加 TarInfo 的某些属性之前修改它们。 如果文件对象不是从文件开头进行定位的普通文件对象,size 之类的属性就可能需要修改。 例如 GzipFile 之类的文件就属于这种情况。 name 也可以被修改,在这种情况下 arcname 可以是一个占位字符串。

TarFile.close()

关闭 TarFile。 在写入模式下,会向归档添加两个表示结束的零数据块。

TarFile.posix

Setting this to True is equivalent to setting the format attribute to USTAR_FORMAT, False is equivalent to GNU_FORMAT.

在 2.4 版更改: posix defaults to False.

2.6 版后已移除: Use the format attribute instead.

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 新版功能: Raises HeaderError if the buffer is invalid..

TarInfo.fromtarfile(tarfile)

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

2.6 新版功能.

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

基于 TarInfo 对象创建一个字符串缓冲区。 有关参数的信息请参见 TarFile 类的构造器。

在 2.6 版更改: The arguments were added.

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

TarInfo.name

归档成员的名称。

TarInfo.size

以字节表示的大小。

TarInfo.mtime

上次修改的时间。

TarInfo.mode

权限位。

TarInfo.type

文件类型。 type 通常为以下常量之一: REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_SPARSE。 要更方便地确定一个 TarInfo 对象的类型,请使用下述的 is*() 方法。

TarInfo.linkname

目标文件名的名称,该属性仅在类型为 LNKTYPESYMTYPETarInfo 对象中存在。

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 格式:

  • The POSIX.1-1988 ustar format (USTAR_FORMAT). It supports filenames up to a length of at best 256 characters and linknames up to 100 characters. The maximum file size is 8 gigabytes. This is an old and limited but widely supported format.

  • The GNU tar format (GNU_FORMAT). It supports long filenames and linknames, files bigger than 8 gigabytes and sparse files. It is the de facto standard on GNU/Linux systems. tarfile fully supports the GNU tar extensions for long names, sparse file support is read-only.

  • 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 问题

The tar format was originally conceived to make backups on tape drives with the main focus on preserving file system information. Nowadays tar archives are commonly used for file distribution and exchanging archives over networks. One problem of the original format (that all other formats are merely variants of) is that there is no concept of supporting different character encodings. For example, an ordinary tar archive created on a UTF-8 system cannot be read correctly on a Latin-1 system if it contains non-ASCII characters. Names (i.e. filenames, linknames, user/group names) containing these characters will appear damaged. Unfortunately, there is no way to autodetect the encoding of an archive.

The pax format was designed to solve this problem. It stores non-ASCII names using the universal character encoding UTF-8. When a pax archive is read, these UTF-8 names are converted to the encoding of the local file system.

The details of unicode conversion are controlled by the encoding and errors keyword arguments of the TarFile class.

The default value for encoding is the local character encoding. It is deduced from sys.getfilesystemencoding() and sys.getdefaultencoding(). In read mode, encoding is used exclusively to convert unicode names from a pax archive to strings in the local character encoding. In write mode, the use of encoding depends on the chosen archive format. In case of PAX_FORMAT, input names that contain non-ASCII characters need to be decoded before being stored as UTF-8 strings. The other formats do not make use of encoding unless unicode objects are used as input names. These are converted to 8-bit character strings before they are added to the archive.

The errors argument defines how characters are treated that cannot be converted to or from encoding. Possible values are listed in section 编解码器基类. In read mode, there is an additional scheme 'utf-8' which means that bad characters are replaced by their UTF-8 representation. This is the default scheme. In write mode the default value for errors is 'strict' to ensure that name information is not altered unnoticed.