13.6. tarfile — 读取与压缩tar文件

源代码: Lib/tarfile.py

tarfile 模块用于读取或者压缩tar文件,可针对gzip、bz2或lzma等格式文件进行相关操作。假如希望对.zip格式文件进行操作,则应使用zipfile模块,或者使用shutil里的高级函数。

一些事实和数字:

  • 如果相应的模块可用,则读取并写入gzipbz2lzma压缩归档。
  • 读/写支持POSIX.1-1988(ustar)格式。
  • 对包括longnamelonglink扩展的GNU tar格式的读/写支持,对稀疏扩展的所有变体的只读支持,包括恢复稀疏文件。
  • 对POSIX.1-2001(pax)格式的读/写支持。
  • 处理目录,常规文件,硬链接,符号链接,fifos,字符设备和块设备,并能够获取和恢复文件信息,如时间戳,访问权限和所有者。

在版本3.3中更改:添加对lzma压缩的支持。

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

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

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

模式行动
'r' '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' 'a:'打开,无需压缩。如果文件不存在,则创建该文件。
'w' 'w:'打开未压缩的写入。
'w:gz'打开gzip压缩写入。
'w:bz2'打开bzip2压缩写。
'w:xz'打开lzma压缩写。

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

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

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

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

模式行动
'r|*'打开用于透明压缩读取的tar块的
'r|'打开未压缩的tar块的以进行读取。
'r|gz'打开gzip压缩的进行阅读。
'r|bz2'打开bzip2压缩的进行阅读。
'r|xz'打开lzma压缩的进行阅读。
'w|'打开未压缩的进行写入。
'w|gz'打开gzip压缩的进行写入。
'w|bz2'打开用于写入的bzip2压缩
'w|xz'打开lzma压缩的进行写入。

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

class tarfile.TarFile

读写tar存档的类。不要直接使用这个类:use tarfile.open()请参阅TarFile Objects

tarfile.is_tarfile(name)

返回True如果名称是tar存档文件,tarfile模块可以读取。

tarfile模块定义了以下例外:

exception tarfile.TarError

所有tarfile异常的基类。

exception tarfile.ReadError

在tar文件打开时引发,或者无法通过tarfile模块处理,或者以某种方式无效。

exception tarfile.CompressionError

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

exception tarfile.StreamError

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

exception tarfile.ExtractError

使用TarFile.extract()时,但仅在TarFile.errorlevel ==时产生非致命错误 2

exception tarfile.HeaderError

TarInfo.frombuf()引发,如果它获得的缓冲区无效。

以下常量在模块级可用:

tarfile.ENCODING

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

以下每个常数定义tarfile模块能够创建的tar归档格式。有关详细信息,请参阅Supported tar formats一节。

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标准模块的文档。
Archiving operations
由标准shutil模块提供的高级存档工具的文档。
GNU tar手动,基本tar格式
tar归档文件的文档,包括GNU tar扩展。

13.6.1. TarFile Objects

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

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

版本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属性存在,则使用该属性。

模式是从现有档案读取'r''a'以将数据附加到现有文件,'w'创建新文件覆盖现有文件,或'x'创建新文件(如果它不存在)。

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

注意

TarFile关闭时,fileobj未关闭。

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

可以使用tarinfo参数替换默认的TarInfo类。

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

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

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

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

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

pax_headers参数是字符串的可选字典,如果格式PAX_FORMAT,则字符串将添加为pax全局标题。

在版本3.2中已更改:使用'surrogateescape'作为错误参数的默认值。

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

classmethod TarFile.open(...)

替代构造函数。The tarfile.open() function is actually a shortcut to this classmethod.

TarFile.getmember(name)

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

注意

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

TarFile.getmembers()

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

TarFile.getnames()

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

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

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

在版本3.5中已更改:添加了成员参数。

TarFile.next()

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

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

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

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

警告

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

在版本3.5中已更改:添加了numeric_only参数。

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

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

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

注意

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

警告

请参阅extractall()的警告。

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

在版本3.5中已更改:添加了numeric_only参数。

TarFile.extractfile(member)

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

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

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

将文件名称添加到归档中。名称可以是任何类型的文件(目录,fifo,符号链接等)。如果给定,arcname指定归档中文件的备用名称。默认情况下,目录以递归方式添加。这可以通过将递归设置为False来避免。如果给出exclude,它必须是一个函数,它需要一个文件名参数并返回一个布尔值。根据此值,相应的文件被排除(True)或添加(False)。如果指定filter,它必须是一个关键字参数。它应该是一个接受TarInfo对象参数并返回更改的TarInfo对象的函数。如果它返回None,则将从档案中排除TarInfo对象。有关示例,请参见Examples

在版本3.2中更改:添加了过滤器参数。

自版本3.2后已弃用: 排除参数已弃用,请改用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对象。该文件由名称命名,或者用文件描述器指定为file object fileobjIf 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. 名称应为文本字符串。

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

TarFile.close()

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

TarFile.pax_headers

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

13.6.2. TarInfo Objects

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

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'作为错误参数的默认值。

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

TarInfo.name

存档成员的名称。

TarInfo.size

大小(字节)。

TarInfo.mtime

上次修改时间。

TarInfo.mode

权限位。

TarInfo.type

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

TarInfo.linkname

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

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. Command Line Interface

版本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. Command line options

-l <tarfile>
--list <tarfile>

在tarfile中列出文件。

-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. Examples

如何将整个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()中的过滤器参数创建归档并重置用户信息:

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. Supported tar formats

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

  • 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 issues

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

tarfile中的字符转换详细信息由TarFile类的编码错误关键字参数控制。

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

errors参数定义如何处理无法转换的字符。可能的值在Error Handlers部分中列出。默认方案是Python还用于其文件系统调用的'surrogateescape',请参阅File Names, Command Line Arguments, and Environment Variables

PAX_FORMAT档案的情况下,通常不需要编码,因为所有元数据都使用UTF-8存储。encoding is only used in the rare cases when binary pax headers are decoded or when strings with surrogate characters are stored.