tarfile读取和写入tar归档文件(6)Python数据压缩和存档(必读进阶Python教程)(参考资料)
该tarfile模块可以读取和写入tar档案,包括使用gzip,bz2和lzma压缩的档案。使用该zipfile模块读取或写入.zip文件,或shutil中的更高级别的功能。
一些事实和数据:
- 如果相应的模块可用
gzip,则读取和写入bz2以及lzma压缩存档。 - 对POSIX.1-1988(ustar)格式的读/写支持。
- 对GNU tar格式的读/写支持,包括longname和longlink 扩展,对稀疏扩展的所有变体的只读支持,包括稀疏文件的恢复。
- 对POSIX.1-2001(pax)格式的读/写支持。
- 处理目录,常规文件,硬链接,符号链接,fifos,字符设备和块设备,并能够获取和恢复文件信息,如时间戳,访问权限和所有者。
版本3.3中已更改:添加了对lzma压缩的支持。
tarfile.open(name = None,mode =’r’,fileobj = None,bufsize = 10240,** kwargs )- 返回
TarFile路径名称的对象。有关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'不可能。如果模式 不适合打开某个(压缩)文件进行读取,ReadError则引发该模式。使用模式'r'来避免这种情况。如果不支持压缩方法,CompressionError则引发该方法。如果指定了fileobj,则它将用作替换以 二进制模式为name打开的文件对象。它应该在0位置。
对于模式
'w:gz','r:gz','w:bz2','r:bz2','x:gz','x:bz2',tarfile.open()接受关键字参数compresslevel(默认9)来指定该文件的压缩级别。出于特殊目的,模式有第二种格式:
'filemode|[compression]'。tarfile.open()将返回一个TarFile对象,该对象将其数据作为块流进行处理。不会对文件进行随机搜索。如果给定,fileobj可以是具有read()或write()方法的任何对象 (取决于模式)。bufsize 指定块大小,默认为字节。将此变体与例如套接字文件对象或磁带设备结合使用。但是,这样的对象受到限制,因为它不允许随机访问,参见示例。目前可能的模式:20 * 512sys.stdinTarFile模式 行动 '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'加入(独家创作)模式。改变在3.6版本:该名称参数接受路径状物体。
- 类
tarfile.TarFile - 用于读写tar档案的类。不要直接使用此类:请
tarfile.open()改用。请参见TarFile对象。
tarfile.is_tarfile(名字)True如果name是tar存档文件,则返回该tarfile模块可以读取的文件。
该tarfile模块定义了以下例外:
- 异常
tarfile.TarError - 所有
tarfile例外的基类。
- 异常
tarfile.ReadError - 在打开tar存档时引发,该
tarfile模块无法由模块处理 或以某种方式无效。
- 异常
tarfile.CompressionError - 在不支持压缩方法或无法正确解码数据时引发。
- 异常
tarfile.StreamError - 针对流类
TarFile对象的典型限制而提出。
- 异常
tarfile.ExtractError - 使用时会引发非致命错误
TarFile.extract(),但仅限于 。TarFile.errorlevel== 2
- 异常
tarfile.HeaderError 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归档文件的文档,包括GNU tar扩展。
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是存档的路径名。name可以是类似路径的对象。如果给出了fileobj,则可以省略它。在这种情况下,如果文件对象的
name属性存在,则使用该属性。mode是
'r'从现有存档读取,'a'将数据附加到现有文件,'w'创建覆盖现有文件的新文件,或'x'仅在新文件尚不存在时创建新文件。如果给出了fileobj,则它用于读取或写入数据。如果可以确定,则fileobj的模式会覆盖模式。fileobj将从位置0使用。
注意
关闭时,fileobj未
TarFile关闭。format控制存档格式。它必须是常量之一
USTAR_FORMAT,GNU_FORMAT或者PAX_FORMAT在模块级别定义。该tarinfo参数可以用来替换缺省
TarInfo使用不同的一类。如果取消引用是
False,加符号和硬链接到存档。如果是True,请将目标文件的内容添加到存档中。这对不支持符号链接的系统没有影响。如果ignore_zeros是
False,则将空块视为存档的结尾。如果是True,则跳过空(和无效)块并尝试获得尽可能多的成员。这仅适用于读取连锁或损坏的档案。debug可以从
0(无调试消息)到3(所有调试消息)设置。邮件被写入sys.stderr。如果是errorlevel
0,则在使用时会忽略所有错误TarFile.extract()。然而,当启用调试时,它们在调试输出中显示为错误消息。如果1,所有致命错误都是OSError异常引发的。如果2,所有非致命错误也会引发TarError异常。该编码和错误参数定义用于读取或写入档案,以及如何转换错误将要处理的字符编码。默认设置适用于大多数用户。有关详细信息,请参阅Unicode问题部分。
所述pax_headers参数是将要添加作为PAX全局头如果串的一个可选的字典的格式是
PAX_FORMAT。在3.2版本中更改:使用
'surrogateescape'作为默认的错误说法。改变在3.5版本:将
'x'加入(独家创作)模式。改变在3.6版本:该名称参数接受路径状物体。
- classmethod
TarFile.open(… ) - 替代构造函数。该
tarfile.open()函数实际上是此类方法的快捷方式。
TarFile.getmember(名字)- 返回
TarInfo成员名称的对象。如果在归档中找不到名称,KeyError则引发。注意
如果成员在归档中出现多次,则其最后一次出现将被假定为最新版本。
TarFile.getmembers()- 将归档的成员作为
TarInfo对象列表返回。该列表与归档中的成员具有相同的顺序。
TarFile.getnames()- 将成员作为名称列表返回。它与返回的列表具有相同的顺序
getmembers()。
TarFile.list(verbose = True,*,members = None )- 打印目录到
sys.stdout。如果是详细的False,则仅打印成员的名称。如果是True,则产生类似于ls -l的输出。如果给出了可选成员,则它必须是返回的列表的子集getmembers()。在3.5版中更改:添加了members参数。
TarFile.next()- 将打开的下一个成员作为
TarInfo对象返回,TarFile打开后进行读取。None如果没有更多可用,请返回。
TarFile.extractall(path =“。”,members = None,*,numeric_owner = False )- 将存档中的所有成员解压缩到当前工作目录或目录路径。如果给出了可选成员,则它必须是返回的列表的子集
getmembers()。提取所有成员后,将设置所有者,修改时间和权限等目录信息。这样做是为了解决两个问题:每次在其中创建文件时,都会重置目录的修改时间。并且,如果目录的权限不允许写入,则向其提取文件将失败。如果numeric_owner是
True,从tar文件的UID和GID数字用于设置所有者/组为所提取的文件。否则,使用tarfile中的命名值。警告
未经事先检查,切勿从不受信任的来源提取档案。文件可能在路径之外创建,例如,具有
"/"以两个点开头的绝对文件名或具有两个点的文件名的成员".."。在3.5版中更改:添加了numeric_owner参数。
改变在3.6版本:该路径参数接受路径状物体。
TarFile.extract(member,path =“”,set_attrs = True,*,numeric_owner = False )- 使用其全名将成员从存档中提取到当前工作目录。其文件信息尽可能准确地提取。member 可以是文件名或
TarInfo对象。您可以使用path指定其他目录。路径可以是类似路径的对象。除非set_attrs为false,否则将设置文件属性(所有者,mtime,模式)。如果numeric_owner是
True,从tar文件的UID和GID数字用于设置所有者/组为所提取的文件。否则,使用tarfile中的命名值。注意
该
extract()方法不处理几个提取问题。在大多数情况下,您应该考虑使用该extractall()方法。警告
请参阅警告
extractall()。版本3.2中已更改:添加了set_attrs参数。
在3.5版中更改:添加了numeric_owner参数。
改变在3.6版本:该路径参数接受路径状物体。
TarFile.extractfile(会员)- 从存档中提取成员作为文件对象。member可以是文件名或
TarInfo对象。如果member是常规文件或链接,io.BufferedReader则返回一个 对象。否则,None返回。在版本3.3中更改:返回一个
io.BufferedReader对象。
TarFile.add(name,arcname = None,recursive = True,*,filter = None )- 将文件名添加到存档。name可以是任何类型的文件(目录,fifo,符号链接等)。如果给定,arcname指定归档中文件的备用名称。默认情况下递归添加目录。这可以通过设置递归来 避免
False。递归按排序顺序添加条目。如果给出了filter,它应该是一个带有TarInfoobject参数并返回已更改TarInfo对象的函数。如果它返回,None则TarInfo对象将从存档中排除。有关示例,请参见示例。版本3.2中已更改:添加了过滤器参数。
版本3.7中已更改:递归按排序顺序添加条目。
TarFile.addfile(tarinfo,fileobj =无)- 将
TarInfo对象tarinfo添加到存档。如果给出了fileobj,它应该是一个二进制文件,并tarinfo.size从中读取字节并将其添加到存档中。您可以TarInfo直接创建对象,也可以使用gettarinfo()。
TarFile.gettarinfo(name = None,arcname = None,fileobj = None )TarInfo从os.stat()现有文件的结果或等效项创建对象。该文件可以按名称命名,也可以指定为带有文件描述符的文件对象 fileobj。 name可以是类似路径的对象。如果给定,arcname为归档中的文件指定备用名称,否则,名称取自fileobj的name属性或name参数。名称应该是文本字符串。您可以
TarInfo在使用之前修改某些属性addfile()。如果文件对象不是位于文件开头的普通文件对象,则size可能需要修改属性。对象就是这种情况GzipFile。的name也可以被修饰,在这种情况下arcname 可能是一个虚设字符串。改变在3.6版本:该名称参数接受路径状物体。
TarFile.close()- 关闭
TarFile。在写入模式下,两个完成零块将附加到存档。
TarFile.pax_headers- 包含pax全局标头的键值对的字典。
TarInfo对象
一个TarInfo对象代表一个成员TarFile。除了存储文件的所有必需属性(如文件类型,大小,时间,权限,所有者等)之外,它还提供了一些有用的方法来确定其类型。它不包含该文件的数据本身。
TarInfo对象由TarFile方法 返回getmember(),getmembers()和gettarinfo()。
- class
tarfile.TarInfo(name =“” ) - 创建一个
TarInfo对象。
- classmethod
TarInfo.frombuf(buf,编码,错误) TarInfo从字符串缓冲区buf创建并返回一个对象。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- 文件类型。 类型通常是这些常量之一:
REGTYPE,AREGTYPE,LNKTYPE,SYMTYPE,DIRTYPE,FIFOTYPE,CONTTYPE,CHRTYPE,BLKTYPE,GNUTYPE_SPARSE。要TarInfo更方便地确定对象的类型,请使用以下is*()方法。
TarInfo.linkname- 目标文件名的名称,仅出现在
TarInfo类型LNKTYPE和的对象中SYMTYPE。
TarInfo.uid- 最初存储此成员的用户的用户标识。
TarInfo.gid- 最初存储此成员的用户的组ID。
TarInfo.uname- 用户名。
TarInfo.gname- 团队名字。
TarInfo.pax_headers- 包含关联的pax扩展头的键值对的字典。
一个TarInfo对象还提供了一些方便的查询方法:
TarInfo.isfile()True如果Tarinfo对象是常规文件,则返回。
TarInfo.isreg()- 与…相同
isfile()。
TarInfo.isdir()True如果是目录则返回。
TarInfo.issym()True如果它是符号链接则返回。
TarInfo.islnk()True如果是硬链接则返回。
TarInfo.ischr()True如果是角色设备则返回。
TarInfo.isblk()True如果它是块设备则返回。
TarInfo.isfifo()True如果是FIFO,则返回。
TarInfo.isdev()True如果它是字符设备,块设备或FIFO之一,则返回。
命令行界面
版本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
命令行选项
-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- 详细输出。
示例
如何将整个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()
支持的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格式的变体,但不兼容。
Unicode问题
tar格式最初被设想为在磁带驱动器上进行备份,主要侧重于保留文件系统信息。如今,tar档案通常用于文件分发和通过网络交换档案。原始格式(所有其他格式的基础)的一个问题是没有支持不同字符编码的概念。例如,如果包含非ASCII,则在Latin-1系统上无法正确读取在UTF-8系统上创建的普通tar存档字符。文本元数据(如文件名,链接名,用户/组名)将显示已损坏。不幸的是,没有办法自动检测存档的编码。pax格式旨在解决此问题。它使用通用字符编码UTF-8存储非ASCII元数据。
字符转换的细节tarfile由类的encoding和errors关键字参数控制 TarFile。
encoding定义用于存档中元数据的字符编码。默认值是sys.getfilesystemencoding()或'ascii' 作为后备。根据是读取还是写入存档,必须对元数据进行解码或编码。如果未正确设置编码,则此转换可能会失败。
所述误差参数定义字符被如何处理不能被转换。错误处理程序一节中列出了可能的值。默认方案是'surrogateescape'Python也用于其文件系统调用,请参阅文件名,命令行参数和环境变量。
在PAX_FORMAT存档的情况下,通常不需要编码,因为所有元数据都使用UTF-8存储。编码仅用于解码二进制pax标头或存储具有代理项字符的字符串的极少数情况。