python3从零学习-5.4.10、shutil — 高阶文件操作

78 篇文章 1 订阅
78 篇文章 0 订阅
源代码:  Lib/shutil.py

shutil  模块提供了一系列对文件和文件集合的高阶操作。 特别是提供了一些支持文件拷贝和删除的函数。 对于单个文件的操作,请参阅  os  模块。
警告
即便是高阶文件拷贝函数 ( shutil.copy() shutil.copy2() ) 也无法拷贝所有的文件元数据。
在 POSIX 平台上,这意味着将丢失文件所有者和组以及 ACL 数据。 在 Mac OS 上,资源钩子和其他元数据不被使用。 这意味着将丢失这些资源并且文件类型和创建者代码将不正确。 在 Windows 上,将不会拷贝文件所有者、ACL 和替代数据流。

目录和文件操作

  • shutil.copyfileobj(fsrc, fdst[, length])

将文件类对象  fsrc  的内容拷贝到文件类对象  fdst 。 整数值  length  如果给出则为缓冲区大小。 特别地,  length  为负值表示拷贝数据时不对源数据进行分块循环处理;默认情况下会分块读取数据以避免不受控制的内存消耗。 请注意如果  fsrc  对象的当前文件位置不为 0,则只有从当前文件位置到文件末尾的内容会被拷贝。
  • shutil.copyfile(src, dst, *, follow_symlinks=True)

将  src  文件的内容(不含元数据)拷贝到  dst  文件并返回  dst 。  src  和  dst  是字符串形式的路径。  dst  必须是完整的目标文件名;对于接受一个目标目录路径的拷贝请参见  shutil.copy() 。 如果  src  和  dst  指定了同一文件,则将引发  SameFileError
目标位置必须是可写的;否则将引发  OSError  异常。 如果  dst  已经存在,它将被替换。 特殊文件如字符或块设备以及管道无法用此函数来拷贝。
如果  follow_symlinks  为假值且  src  为符号链接,则将创建一个新的符号链接而不是拷贝  src  所指向的文件。
在 3.3 版更改:  曾经是引发  IOError  而不是  OSError 。 增加了  follow_symlinks  参数。 现在是返回  dst
在 3.4 版更改:  引发  SameFileError  而不是  Error 。 由于前者是后者的子类,此改变是向后兼容的。

exception shutil.SameFileError

此异常会在 copyfile() 中的源和目标为同一文件时被引发。
3.4 新版功能.
  • shutil.copymode(src, dst, *, follow_symlinks=True)

从  src  拷贝权限位到  dst 。 文件的内容、所有者和分组将不受影响。  src  和  dst  均为字符串形式的路径名。 如果  follow_symlinks  为假值,并且  src  和  dst  均为符号链接, copymode()  将尝试修改  dst  本身的模式(而非它所指向的文件)。 此功能并不是在所有平台上均可用;请参阅  copystat()  了解详情。 如果  copymode()  无法修改本机平台上的符号链接,而它被要求这样做,它将不做任何操作即返回。
在 3.3 版更改:  加入  follow_symlinks  参数。
  • shutil.copystat(src, dst, *, follow_symlinks=True)

从  src  拷贝权限位、最近访问时间、最近修改时间以及旗标到  dst 。 在 Linux 上, copystat()  还会在可能的情况下拷贝“扩展属性”。 文件内容、所有者和分组将不受影响。  src  和  dst  均为字符串形式的路径名。
如果  follow_symlinks  为假值,并且  src  和  dst  均指向符号链接, copystat()  将作用于符号链接本身而非该符号链接所指向的文件 — 从  src  符号链接读取信息,并将信息写入  dst  符号链接。
注解
并非所有平台者提供检查和修改符号链接的功能。 Python 本身可以告诉你哪些功能是在本机上可用的。
  • 如果  os.chmod  in  os.supports_follow_symlinks  为  True ,则  copystat()  可以修改符号链接的权限位。
  • 如果  os.utime  in  os.supports_follow_symlinks  为  True ,则  copystat()  可以修改符号链接的最近访问和修改时间。
  • 如果  os.chflags  in  os.supports_follow_symlinks  为  True ,则  copystat()  可以修改符号链接的旗标。 ( os.chflags  不是在所有平台上均可用。)
在此功能部分或全部不可用的平台上,当被要求修改一个符号链接时, copystat()  将尽量拷贝所有内容。  copystat()  一定不会返回失败信息。
更多信息请参阅  os.supports_follow_symlinks
在 3.3 版更改:  添加了  follow_symlinks  参数并且支持 Linux 扩展属性。
  • shutil.copy(src, dst, *, follow_symlinks=True)

将文件  src  拷贝到文件或目录  dst 。  src  和  dst  应为字符串。 如果  dst  指定了一个目录,文件将使用  src  中的基准文件名拷贝到  dst 。 返回新创建文件所对应的路径。
如果  follow_symlinks  为假值且  src  为符号链接,则  dst  也将被创建为符号链接。 如果  follow_symlinks  为真值且  src  为符号链接, dst  将成为  src  所指向的文件的一个副本。
copy()  会拷贝文件数据和文件的权限模式 (参见  os.chmod() )。 其他元数据,例如文件的创建和修改时间不会被保留。 要保留所有原有的元数据,请改用  copy2()  。
在 3.3 版更改:  添加了  follow_symlinks  参数。 现在会返回新创建文件的路径。
  • shutil.copy2(src, dst, *, follow_symlinks=True)

类似于  copy() ,区别在于  copy2()  还会尝试保留文件的元数据。
当  follow_symlinks  为假值且  src  为符号链接时, copy2()  会尝试将来自  src  符号链接的所有元数据拷贝到新创建的  dst  符号链接。 但是,此功能不是在所有平台上均可用。 在此功能部分或全部不可用的平台上, copy2()  将尽量保留所有元数据; copy2()  一定不会返回失败的结果。
copy2()  会使用  copystat()  来拷贝文件元数据。 请参阅  copystat()  了解有关修改符号链接元数据的平台支持的更多信息。
在 3.3 版更改:  添加了  follow_symlinks  参数,还会尝试拷贝扩展文件系统属性(目前仅限 Linux)。 现在会返回新创建文件的路径。
  • shutil.ignore_patterns(*patterns)

这个工厂函数会创建一个函数,它可被用作  copytree()  的  ignore  可调用对象参数,以忽略那些匹配所提供的 glob 风格的  patterns  之一的文件和目录。 参见以下示例。
  • shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)

递归地拷贝以  src  为根路径的整个目录树,返回目标目录。 名为  dst  的目标目录不必已存在;它本身和还不存在的父目录都将被自动创建。 目录的权限和时间信息将通过  copystat()  来拷贝,单独的文件将使用  shutil.copy2()  来拷贝。
如果  symlinks  为真值,源目录树中的符号链接会在新目录树中表示为符号链接,并且原链接的元数据在平台允许的情况下也会被拷贝;如果为假值或省略,则会将被链接文件的内容和元数据拷贝到新目录树。
当  symlinks  为假值时,如果符号链接所指向的文件不存在,则会在拷贝进程的末尾将一个异常添加到  Error  异常中的错误列表。 如果你希望屏蔽此异常那就将可选的  ignore_dangling_symlinks  旗标设为真值。 请注意此选项在不支持  os.symlink()  的平台上将不起作用。
如果给出了  ignore ,它必须是一个可调用对象,该对象将接受  copytree()  所访问的目录以及  os.listdir()  所返回的目录内容列表作为其参数。 由于  copytree()  是递归地被调用的, ignore  可调用对象对于每个被拷贝目录都将被调用一次。 该可调用对象必须返回一个相对于当前目录的目录和文件名序列(即其第二个参数的子集);随后这些名称将在拷贝进程中被忽略。  ignore_patterns()  可被用于创建这种基于 glob 风格模式来忽略特定名称的可调用对象。
如果发生了异常,将引发一个附带原因列表的  Error
如果给出了  copy_function ,它必须是一个将被用来拷贝每个文件的可调用对象。 它在被调用时会将源路径和目标路径作为参数传入。 默认情况下, shutil.copy2()  将被使用,但任何支持同样签名(与  shutil.copy()  一致)的函数都可以使用。
在 3.3 版更改:  当  symlinks  为假值时拷贝元数据。 现在会返回  dst
在 3.2 版更改:  添加了  copy_function  参数以允许提供定制的拷贝函数。 添加了  ignore_dangling_symlinks  参数以便在  symlinks  为假值时屏蔽符号链接错误。
  • shutil.rmtree(path, ignore_errors=False, οnerrοr=None)

删除一个完整的目录树; path  必须指向一个目录(但不能是一个目录的符号链接)。 如果  ignore_errors  为真值,删除失败导致的错误将被忽略;如果为假值或是省略,此类错误将通过调用由  onerror  所指定的处理程序来处理,或者如果此参数被省略则将引发一个异常。
注解
在支持必要的基于 fd 的函数的平台上,默认会使用  rmtree()  的可防御符号链接攻击的版本。 在其他平台上, rmtree()  较易遭受符号链接攻击:给定适当的时间和环境,攻击者可以操纵文件系统中的符号链接来删除他们在其他情况下无法访问的文件。 应用程序可以使用  rmtree.avoids_symlink_attacks  函数属性来确定此类情况具体是哪一些。
如果提供了  onerror ,它必须为接受三个形参的可调用对象:  function path  和  excinfo
第一个形参  function  是引发异常的函数;它依赖于具体的平台和实现。 第二个形参  path  将是传递给  function  的路径名。 第三个形参  excinfo  将是由  sys.exc_info()  所返回的异常信息。 由  onerror  所引发的异常将不会被捕获。
在 3.3 版更改:  添加了一个防御符号链接攻击的版本,如果平台支持基于 fd 的函数就会被使用。

rmtree.avoids_symlink_attacks

指明当前平台和实现是否提供防御符号链接攻击的 rmtree() 版本。 目前它仅在平台支持基于 fd 的目录访问函数时才返回真值。
3.3 新版功能.
  • shutil.move(src, dst, copy_function=copy2)

递归地将一个文件或目录 ( src ) 移至另一位置 ( dst ) 并返回目标位置。
如果目标是已存在的目录,则  src  会被移至该目录下。 如果目标已存在但不是目录,它可能会被覆盖,具体取决于  os.rename()  的语义。
如果目标是在当前文件系统中,则会使用  os.rename() 。 在其他情况下, src  将被拷贝至  dst ,使用的函数为  copy_function ,然后目标会被移除。 对于符号链接,则将在  dst  之下或以其本身为名称创建一个指向  src  目标的新符号链接,并且  src  将被移除。
如果给出了  copy_function ,则它必须为接受两个参数  src  和  dst  的可调用对象,并会在  os.rename()  无法使用时被用来将  src  拷贝到  dest 。 如果源位置是一个目录,则会调用  copytree() ,并向它传入  copy_function() 。 默认的  copy_function  是  copy2() 。 使用  copy()  作为  copy_function  允许在无法附带拷贝元数据时让移动操作成功执行,但其代价是不拷贝任何元数据。
在 3.3 版更改:  为异类文件系统添加了显式的符号链接处理,以便使它适应 GNU 的  mv  的行为。 现在会返回  dst
在 3.5 版更改:  增加了  copy_function  关键字参数。
  • shutil.disk_usage(path)

返回给定路径的磁盘使用统计数据,形式为一个  named tuple ,其中包含  total used  和  free  属性,分别表示总计、已使用和未使用空间的字节数。 在 Windows 上, path  必须是一个目录;在 Unix 上,它可以是一个文件或一个目录。
3.3 新版功能.
Availability: Unix, Windows.
  • shutil.chown(path, user=None, group=None)

修改给定  path  的所有者  user  和/或  group
user  可以是一个系统用户名或 uid; group  同样如此。 要求至少有一个参数。
另请参阅下层的函数  os.chown()
Availability: Unix.
3.3 新版功能.
  • shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None)

返回当给定的  cmd  被调用时将要运行的可执行文件的路径。 如果没有  cmd  会被调用则返回  None
mode  是一个传递给  os.access()  的权限掩码,在默认情况下将确定文件是否存在并且为可执行文件。
当未指定  path  时,将会使用  os.environ()  的结果,返回 “PATH” 的值或回退为  os.defpath
在 Windows 上当前目录总是会被添加为  path  的第一项,无论你是否使用默认值或提供你自己的路径,这是命令行终端在查找可执行文件时所采用的行为方式。 此外,当在  path  中查找  cmd  时,还会检查  PATHEXT  环境变量。 例如,如果你调用  shutil.which("python") which()  将搜索  PATHEXT  来确定它要在  path  目录中查找  python.exe 。 例如,在 Windows 上:
>>> shutil . which( "python" )
'C:\\Python33\\python.EXE'
3.3 新版功能.

exception shutil.Error

此异常会收集在多文件操作期间所引发的异常。 对于 copytree(),此异常参数将是一个由三元组 (srcnamedstnameexception) 构成的列表。

copytree 示例

这个示例就是上面所描述的  copytree()  函数的实现,其中省略了文档字符串。 它还展示了此模块所提供的许多其他函数。
def copytree (src, dst, symlinks = False ):
    names = os . listdir(src)
    os . makedirs(dst)
    errors = []
    for name in names:
        srcname = os . path . join(src, name)
        dstname = os . path . join(dst, name)
        try :
            if symlinks and os . path . islink(srcname):
                linkto = os . readlink(srcname)
                os . symlink(linkto, dstname)
            elif os . path . isdir(srcname):
                copytree(srcname, dstname, symlinks)
            else :
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except OSError as why:
            errors . append((srcname, dstname, str (why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors . extend(err . args[ 0 ])
    try :
        copystat(src, dst)
    except OSError as why:
        # can't copy file access times on Windows
        if why . winerror is None :
            errors . extend((src, dst, str (why)))
    if errors:
        raise Error(errors)
另一个使用  ignore_patterns()  辅助函数的例子:
from shutil import copytree, ignore_patterns
 
copytree(source, destination, ignore = ignore_patterns( '*.pyc' , 'tmp*' ))
这将会拷贝除  .pyc  文件和以  tmp  打头的文件或目录以外的所有条目.
另一个使用  ignore  参数来添加记录调用的例子:
from shutil import copytree
import logging
 
def _logpath (path, names):
    logging . info( 'Working in %s ' , path)
    return []   # nothing will be ignored
 
copytree(source, destination, ignore = _logpath)

rmtree 示例

这个例子演示了如何在 Windows 上删除一个目录树,其中部分文件设置了只读属性位。 它会使用 onerror 回调函数来清除只读属性位并再次尝试删除。 任何后续的失败都将被传播。
import os , stat
import shutil
 
def remove_readonly (func, path, _):
    "Clear the readonly bit and reattempt the removal"
    os . chmod(path, stat . S_IWRITE)
    func(path)
 
shutil . rmtree(directory, onerror = remove_readonly)

归档操作

3.2 新版功能.
在 3.5 版更改:  添加了对  xztar  格式的支持。
本模块也提供了用于创建和读取压缩和归档文件的高层级工具。 它们依赖于  zipfile  和  tarfile  模块。
  • shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])

创建一个归档文件(例如 zip 或 tar)并返回其名称。
base_name  是要创建的文件名称,包括路径,去除任何特定格式的扩展名。  format  是归档格式:为 “zip” (如果  zlib  模块可用), “tar”, “gztar” (如果  zlib  模块可用), “bztar” (如果  bz2  模块可用) 或 “xztar” (如果  lzma  模块可用) 中的一个。
root_dir  是一个目录,它将作为归档文件的根目录;例如,我们通常会在创建归档文件之前用 chdir 命令切换到  root_dir
base_dir  是我们要执行归档的起始目录;也就是说  base_dir  将成为归档文件中所有文件和目录共有的路径前缀。
root_dir  和  base_dir  默认均为当前目录。
如果  dry_run  为真值,则不会创建归档文件,但将要被执行的操作会被记录到  logger
owner  和  group  将在创建 tar 归档文件时被使用。 默认会使用当前的所有者和分组。
logger  必须是一个兼容  PEP 282  的对象,通常为  logging.Logger  的实例。
verbose  参数已不再使用并进入弃用状态。
  • shutil.get_archive_formats()

返回支持的归档格式列表。 所返回序列中的每个元素为一个元组  (name,  description)
默认情况下  shutil  提供以下格式:
  • zip : ZIP 文件(如果  zlib  模块可用)。
  • tar : 未压缩的 tar 文件。
  • gztar : gzip 压缩的 tar 文件(如果  zlib  模块可用)。
  • bztar : bzip2 压缩的 tar 文件(如果  bz2  模块可用)。
  • xztar : xz 压缩的 tar 文件(如果  lzma  模块可用)。
你可以通过使用  register_archive_format()  注册新的格式或为任何现有格式提供你自己的归档程序。
  • shutil.register_archive_format(name, function[, extra_args[, description]])

为  name  格式注册一个归档程序。
function  是将被用来解包归档文件的可调用对象。 该可调用对象将接收要创建文件的  base_name ,再加上要归档内容的  base_dir  (其默认值为  os.curdir )。 更多参数会被作为关键字参数传入:  owner group dry_run  和  logger  (与向  make_archive()  传入的参数一致)。
如果给出了  extra_args ,则其应为一个  (name,  value)  对的序列,将在归档器可调用对象被使用时作为附加的关键字参数。
description  由  get_archive_formats()  使用,它将返回归档器的列表。 默认值为一个空字符串。
  • shutil.unregister_archive_format(name)

从支持的格式中移除归档格式  name
  • shutil.unpack_archive(filename[, extract_dir[, format]])

解包一个归档文件。  filename  是归档文件的完整路径。
extract_dir  是归档文件解包的目标目录名称。 如果未提供,则将使用当前工作目录。
format  是归档格式:应为 “zip”, “tar”, “gztar”, “bztar” 或 “xztar” 之一。 或者任何通过  register_unpack_format()  注册的其他格式。 如果未提供, unpack_archive()  将使用归档文件的后缀来检查是否注册了对应于该后缀的解包器。 在未找到任何解包器的情况下,将引发  ValueError
  • shutil.register_unpack_format(name, extensions, function[, extra_args[, description]])

注册一个解包格式。  name  为格式名称而  extensions  为对应于该格式的扩展名列表,例如 Zip 文件的扩展名为  .zip
function  是将被用来解包归档文件的可调用对象。 该可调用对象将接受归档文件的路径,加上该归档文件要被解包的目标目录。
如果提供了  extra_args ,则其应为一个  (name,  value)  元组的序列,将被作为关键字参数传递给该可调用对象。
可以提供  description  来描述该格式,它将被  get_unpack_formats()  返回。
  • shutil.unregister_unpack_format(name)

撤销注册一个解包格式。  name  为格式的名称。
  • shutil.get_unpack_formats()

返回所有已注册的解包格式列表。 所返回序列中的每个元素为一个元组  (name,  extensions,  description)
默认情况下  shutil  提供以下格式:
  • zip : ZIP 文件(只有在相应模块可用时才能解包压缩文件)。
  • tar : 未压缩的 tar 文件。
  • gztar : gzip 压缩的 tar 文件(如果  zlib  模块可用)。
  • bztar : bzip2 压缩的 tar 文件(如果  bz2  模块可用)。
  • xztar : xz 压缩的 tar 文件(如果  lzma  模块可用)。
你可以通过使用  register_unpack_format()  注册新的格式或为任何现有格式提供你自己的解包器。

归档程序示例

在这个示例中,我们创建了一个 gzip 压缩的 tar 归档文件,其中包含用户的  .ssh  目录下的所有文件:
>>> from shutil import make_archive
>>> import os
>>> archive_name = os . path . expanduser(os . path . join( '~' , 'myarchive' ))
>>> root_dir = os . path . expanduser(os . path . join( '~' , '.ssh' ))
>>> make_archive(archive_name, 'gztar' , root_dir)
'/Users/tarek/myarchive.tar.gz'
结果归档文件中包含有:
$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts

查询输出终端的尺寸

  • shutil.get_terminal_size(fallback=(columns, lines))

获取终端窗口的尺寸。
对于两个维度中的每一个,会分别检查环境变量  COLUMNS  和  LINES 。 如果定义了这些变量并且其值为正整数,则将使用这些值。
如果未定义  COLUMNS  或  LINES ,这是通常的情况,则连接到  sys.__stdout__  的终端将通过发起调用  os.get_terminal_size()  被查询。
如果由于系统不支持查询,或是由于我们未连接到某个终端而导致查询终端尺寸不成功,则会使用在  fallback  形参中给出的值。  fallback  默认为  (80,  24) ,这是许多终端模拟器所使用的默认尺寸。
返回的值是一个  os.terminal_size  类型的具名元组。
另请参阅: The Single UNIX Specification, Version 2,  Other Environment Variables .
3.3 新版功能.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值