• python之模块之shutil模块


    shutil

      -- --High-level file operations  高级的文件操作模块。

      os模块提供了对目录或者文件的新建/删除/查看文件属性,还提供了对文件以及目录的路径操作。比如说:绝对路径,父目录……  但是,os文件的操作还应该包含移动 复制  打包 压缩 解压等操作,这些os模块都没有提供。

      而本章所讲的shutil则就是对os中文件操作的补充。--移动 复制  打包 压缩 解压,

    shutil功能:

    1  shutil.copyfileobj(fsrc, fdst[, length=16*1024])    #copy文件内容到另一个文件,可以copy指定大小的内容

     1 #先来看看其源代码。
     2 def copyfileobj(fsrc, fdst, length=16*1024):
     3     """copy data from file-like object fsrc to file-like object fdst"""
     4     while 1:
     5         buf = fsrc.read(length)
     6         if not buf:
     7             break
     8         fdst.write(buf)
     9 
    10 #注意! 在其中fsrc,fdst都是文件对象,都需要打开后才能进行复制操作
    11 import shutil
    12 f1=open('name','r')
    13 f2=open('name_copy','w+')
    14 shutil.copyfileobj(f1,f2,length=16*1024)

    2  shutil.copyfile(src,dst)   #copy文件内容,是不是感觉上面的文件复制很麻烦?还需要自己手动用open函数打开文件,在这里就不需要了,事实上,copyfile调用了copyfileobj

     1 def copyfile(src, dst, *, follow_symlinks=True):
     2     """Copy data from src to dst.
     3 
     4     If follow_symlinks is not set and src is a symbolic link, a new
     5     symlink will be created instead of copying the file it points to.
     6 
     7     """
     8     if _samefile(src, dst):
     9         raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
    10 
    11     for fn in [src, dst]:
    12         try:
    13             st = os.stat(fn)
    14         except OSError:
    15             # File most likely does not exist
    16             pass
    17         else:
    18             # XXX What about other special files? (sockets, devices...)
    19             if stat.S_ISFIFO(st.st_mode):
    20                 raise SpecialFileError("`%s` is a named pipe" % fn)
    21 
    22     if not follow_symlinks and os.path.islink(src):
    23         os.symlink(os.readlink(src), dst)
    24     else:
    25         with open(src, 'rb') as fsrc:
    26             with open(dst, 'wb') as fdst:
    27                 copyfileobj(fsrc, fdst)
    28     return dst
    29 
    30 查看源代码
    1 shutil.copyfile('name','name_copy_2')
    2 #一句就可以实现复制文件内容

    3  shutil.copymode(src,dst)   #仅copy权限,不更改文件内容,组和用户。

     1 def copymode(src, dst, *, follow_symlinks=True):
     2     """Copy mode bits from src to dst.
     3 
     4     If follow_symlinks is not set, symlinks aren't followed if and only
     5     if both `src` and `dst` are symlinks.  If `lchmod` isn't available
     6     (e.g. Linux) this method does nothing.
     7 
     8     """
     9     if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
    10         if hasattr(os, 'lchmod'):
    11             stat_func, chmod_func = os.lstat, os.lchmod
    12         else:
    13             return
    14     elif hasattr(os, 'chmod'):
    15         stat_func, chmod_func = os.stat, os.chmod
    16     else:
    17         return
    18 
    19     st = stat_func(src)
    20     chmod_func(dst, stat.S_IMODE(st.st_mode))
    21 
    22 查看源代码
     1 def copymode(src, dst, *, follow_symlinks=True):
     2     """Copy mode bits from src to dst.
     3 
     4     If follow_symlinks is not set, symlinks aren't followed if and only
     5     if both `src` and `dst` are symlinks.  If `lchmod` isn't available
     6     (e.g. Linux) this method does nothing.
     7 
     8     """
     9     if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
    10         if hasattr(os, 'lchmod'):
    11             stat_func, chmod_func = os.lstat, os.lchmod
    12         else:
    13             return
    14     elif hasattr(os, 'chmod'):
    15         stat_func, chmod_func = os.stat, os.chmod
    16     else:
    17         return
    18 
    19     st = stat_func(src)
    20     chmod_func(dst, stat.S_IMODE(st.st_mode))
    21 
    22 查看源代码

    4  shutil.copystat(src,dst)    #复制所有的状态信息,包括权限,组,用户,时间等

     1 def copystat(src, dst, *, follow_symlinks=True):
     2     """Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
     3 
     4     If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
     5     only if both `src` and `dst` are symlinks.
     6 
     7     """
     8     def _nop(*args, ns=None, follow_symlinks=None):
     9         pass
    10 
    11     # follow symlinks (aka don't not follow symlinks)
    12     follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))
    13     if follow:
    14         # use the real function if it exists
    15         def lookup(name):
    16             return getattr(os, name, _nop)
    17     else:
    18         # use the real function only if it exists
    19         # *and* it supports follow_symlinks
    20         def lookup(name):
    21             fn = getattr(os, name, _nop)
    22             if fn in os.supports_follow_symlinks:
    23                 return fn
    24             return _nop
    25 
    26     st = lookup("stat")(src, follow_symlinks=follow)
    27     mode = stat.S_IMODE(st.st_mode)
    28     lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
    29         follow_symlinks=follow)
    30     try:
    31         lookup("chmod")(dst, mode, follow_symlinks=follow)
    32     except NotImplementedError:
    33         # if we got a NotImplementedError, it's because
    34         #   * follow_symlinks=False,
    35         #   * lchown() is unavailable, and
    36         #   * either
    37         #       * fchownat() is unavailable or
    38         #       * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
    39         #         (it returned ENOSUP.)
    40         # therefore we're out of options--we simply cannot chown the
    41         # symlink.  give up, suppress the error.
    42         # (which is what shutil always did in this circumstance.)
    43         pass
    44     if hasattr(st, 'st_flags'):
    45         try:
    46             lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
    47         except OSError as why:
    48             for err in 'EOPNOTSUPP', 'ENOTSUP':
    49                 if hasattr(errno, err) and why.errno == getattr(errno, err):
    50                     break
    51             else:
    52                 raise
    53     _copyxattr(src, dst, follow_symlinks=follow)
    54 
    55 查看源代码

    5  shutil.copy(src,dst)   #复制文件的内容以及权限,先copyfile后copymode

     1 def copy(src, dst, *, follow_symlinks=True):
     2     """Copy data and mode bits ("cp src dst"). Return the file's destination.
     3 
     4     The destination may be a directory.
     5 
     6     If follow_symlinks is false, symlinks won't be followed. This
     7     resembles GNU's "cp -P src dst".
     8 
     9     If source and destination are the same file, a SameFileError will be
    10     raised.
    11 
    12     """
    13     if os.path.isdir(dst):
    14         dst = os.path.join(dst, os.path.basename(src))
    15     copyfile(src, dst, follow_symlinks=follow_symlinks)
    16     copymode(src, dst, follow_symlinks=follow_symlinks)
    17     return dst
    18 
    19 查看源代码

    6  shutil.copy2(src,dst)    #复制文件的内容以及文件的所有状态信息。先copyfile后copystat

     1 def copy2(src, dst, *, follow_symlinks=True):
     2     """Copy data and all stat info ("cp -p src dst"). Return the file's
     3     destination."
     4 
     5     The destination may be a directory.
     6 
     7     If follow_symlinks is false, symlinks won't be followed. This
     8     resembles GNU's "cp -P src dst".
     9 
    10     """
    11     if os.path.isdir(dst):
    12         dst = os.path.join(dst, os.path.basename(src))
    13     copyfile(src, dst, follow_symlinks=follow_symlinks)
    14     copystat(src, dst, follow_symlinks=follow_symlinks)
    15     return dst
    16 
    17 查看源代码

     7  shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False)   #递归的复制文件内容及状态信息

     1 def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
     2              ignore_dangling_symlinks=False):
     3     """Recursively copy a directory tree.
     4 
     5     The destination directory must not already exist.
     6     If exception(s) occur, an Error is raised with a list of reasons.
     7 
     8     If the optional symlinks flag is true, symbolic links in the
     9     source tree result in symbolic links in the destination tree; if
    10     it is false, the contents of the files pointed to by symbolic
    11     links are copied. If the file pointed by the symlink doesn't
    12     exist, an exception will be added in the list of errors raised in
    13     an Error exception at the end of the copy process.
    14 
    15     You can set the optional ignore_dangling_symlinks flag to true if you
    16     want to silence this exception. Notice that this has no effect on
    17     platforms that don't support os.symlink.
    18 
    19     The optional ignore argument is a callable. If given, it
    20     is called with the `src` parameter, which is the directory
    21     being visited by copytree(), and `names` which is the list of
    22     `src` contents, as returned by os.listdir():
    23 
    24         callable(src, names) -> ignored_names
    25 
    26     Since copytree() is called recursively, the callable will be
    27     called once for each directory that is copied. It returns a
    28     list of names relative to the `src` directory that should
    29     not be copied.
    30 
    31     The optional copy_function argument is a callable that will be used
    32     to copy each file. It will be called with the source path and the
    33     destination path as arguments. By default, copy2() is used, but any
    34     function that supports the same signature (like copy()) can be used.
    35 
    36     """
    37     names = os.listdir(src)
    38     if ignore is not None:
    39         ignored_names = ignore(src, names)
    40     else:
    41         ignored_names = set()
    42 
    43     os.makedirs(dst)
    44     errors = []
    45     for name in names:
    46         if name in ignored_names:
    47             continue
    48         srcname = os.path.join(src, name)
    49         dstname = os.path.join(dst, name)
    50         try:
    51             if os.path.islink(srcname):
    52                 linkto = os.readlink(srcname)
    53                 if symlinks:
    54                     # We can't just leave it to `copy_function` because legacy
    55                     # code with a custom `copy_function` may rely on copytree
    56                     # doing the right thing.
    57                     os.symlink(linkto, dstname)
    58                     copystat(srcname, dstname, follow_symlinks=not symlinks)
    59                 else:
    60                     # ignore dangling symlink if the flag is on
    61                     if not os.path.exists(linkto) and ignore_dangling_symlinks:
    62                         continue
    63                     # otherwise let the copy occurs. copy2 will raise an error
    64                     if os.path.isdir(srcname):
    65                         copytree(srcname, dstname, symlinks, ignore,
    66                                  copy_function)
    67                     else:
    68                         copy_function(srcname, dstname)
    69             elif os.path.isdir(srcname):
    70                 copytree(srcname, dstname, symlinks, ignore, copy_function)
    71             else:
    72                 # Will raise a SpecialFileError for unsupported file types
    73                 copy_function(srcname, dstname)
    74         # catch the Error from the recursive copytree so that we can
    75         # continue with other files
    76         except Error as err:
    77             errors.extend(err.args[0])
    78         except OSError as why:
    79             errors.append((srcname, dstname, str(why)))
    80     try:
    81         copystat(src, dst)
    82     except OSError as why:
    83         # Copying file access times may fail on Windows
    84         if getattr(why, 'winerror', None) is None:
    85             errors.append((src, dst, str(why)))
    86     if errors:
    87         raise Error(errors)
    88     return dst
    89 
    90 # version vulnerable to race conditions
    91 
    92 查看源代码
     1 def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
     2              ignore_dangling_symlinks=False):
     3     """Recursively copy a directory tree.
     4 
     5     The destination directory must not already exist.
     6     If exception(s) occur, an Error is raised with a list of reasons.
     7 
     8     If the optional symlinks flag is true, symbolic links in the
     9     source tree result in symbolic links in the destination tree; if
    10     it is false, the contents of the files pointed to by symbolic
    11     links are copied. If the file pointed by the symlink doesn't
    12     exist, an exception will be added in the list of errors raised in
    13     an Error exception at the end of the copy process.
    14 
    15     You can set the optional ignore_dangling_symlinks flag to true if you
    16     want to silence this exception. Notice that this has no effect on
    17     platforms that don't support os.symlink.
    18 
    19     The optional ignore argument is a callable. If given, it
    20     is called with the `src` parameter, which is the directory
    21     being visited by copytree(), and `names` which is the list of
    22     `src` contents, as returned by os.listdir():
    23 
    24         callable(src, names) -> ignored_names
    25 
    26     Since copytree() is called recursively, the callable will be
    27     called once for each directory that is copied. It returns a
    28     list of names relative to the `src` directory that should
    29     not be copied.
    30 
    31     The optional copy_function argument is a callable that will be used
    32     to copy each file. It will be called with the source path and the
    33     destination path as arguments. By default, copy2() is used, but any
    34     function that supports the same signature (like copy()) can be used.
    35 
    36     """
    37     names = os.listdir(src)
    38     if ignore is not None:
    39         ignored_names = ignore(src, names)
    40     else:
    41         ignored_names = set()
    42 
    43     os.makedirs(dst)
    44     errors = []
    45     for name in names:
    46         if name in ignored_names:
    47             continue
    48         srcname = os.path.join(src, name)
    49         dstname = os.path.join(dst, name)
    50         try:
    51             if os.path.islink(srcname):
    52                 linkto = os.readlink(srcname)
    53                 if symlinks:
    54                     # We can't just leave it to `copy_function` because legacy
    55                     # code with a custom `copy_function` may rely on copytree
    56                     # doing the right thing.
    57                     os.symlink(linkto, dstname)
    58                     copystat(srcname, dstname, follow_symlinks=not symlinks)
    59                 else:
    60                     # ignore dangling symlink if the flag is on
    61                     if not os.path.exists(linkto) and ignore_dangling_symlinks:
    62                         continue
    63                     # otherwise let the copy occurs. copy2 will raise an error
    64                     if os.path.isdir(srcname):
    65                         copytree(srcname, dstname, symlinks, ignore,
    66                                  copy_function)
    67                     else:
    68                         copy_function(srcname, dstname)
    69             elif os.path.isdir(srcname):
    70                 copytree(srcname, dstname, symlinks, ignore, copy_function)
    71             else:
    72                 # Will raise a SpecialFileError for unsupported file types
    73                 copy_function(srcname, dstname)
    74         # catch the Error from the recursive copytree so that we can
    75         # continue with other files
    76         except Error as err:
    77             errors.extend(err.args[0])
    78         except OSError as why:
    79             errors.append((srcname, dstname, str(why)))
    80     try:
    81         copystat(src, dst)
    82     except OSError as why:
    83         # Copying file access times may fail on Windows
    84         if getattr(why, 'winerror', None) is None:
    85             errors.append((src, dst, str(why)))
    86     if errors:
    87         raise Error(errors)
    88     return dst
    89 
    90 # version vulnerable to race conditions
    91 
    92 查看源代码

    8  shutil.rmtree(path, ignore_errors=False, onerror=None)   #递归地删除文件

     1 def rmtree(path, ignore_errors=False, onerror=None):
     2     """Recursively delete a directory tree.
     3 
     4     If ignore_errors is set, errors are ignored; otherwise, if onerror
     5     is set, it is called to handle the error with arguments (func,
     6     path, exc_info) where func is platform and implementation dependent;
     7     path is the argument to that function that caused it to fail; and
     8     exc_info is a tuple returned by sys.exc_info().  If ignore_errors
     9     is false and onerror is None, an exception is raised.
    10 
    11     """
    12     if ignore_errors:
    13         def onerror(*args):
    14             pass
    15     elif onerror is None:
    16         def onerror(*args):
    17             raise
    18     if _use_fd_functions:
    19         # While the unsafe rmtree works fine on bytes, the fd based does not.
    20         if isinstance(path, bytes):
    21             path = os.fsdecode(path)
    22         # Note: To guard against symlink races, we use the standard
    23         # lstat()/open()/fstat() trick.
    24         try:
    25             orig_st = os.lstat(path)
    26         except Exception:
    27             onerror(os.lstat, path, sys.exc_info())
    28             return
    29         try:
    30             fd = os.open(path, os.O_RDONLY)
    31         except Exception:
    32             onerror(os.lstat, path, sys.exc_info())
    33             return
    34         try:
    35             if os.path.samestat(orig_st, os.fstat(fd)):
    36                 _rmtree_safe_fd(fd, path, onerror)
    37                 try:
    38                     os.rmdir(path)
    39                 except OSError:
    40                     onerror(os.rmdir, path, sys.exc_info())
    41             else:
    42                 try:
    43                     # symlinks to directories are forbidden, see bug #1669
    44                     raise OSError("Cannot call rmtree on a symbolic link")
    45                 except OSError:
    46                     onerror(os.path.islink, path, sys.exc_info())
    47         finally:
    48             os.close(fd)
    49     else:
    50         return _rmtree_unsafe(path, onerror)
    51 
    52 # Allow introspection of whether or not the hardening against symlink
    53 # attacks is supported on the current platform
    54 rmtree.avoids_symlink_attacks = _use_fd_functions
    55 
    56 查看源代码

    9  shutil.move(src, dst)    #递归的移动文件

     1 def move(src, dst):
     2     """Recursively move a file or directory to another location. This is
     3     similar to the Unix "mv" command. Return the file or directory's
     4     destination.
     5 
     6     If the destination is a directory or a symlink to a directory, the source
     7     is moved inside the directory. The destination path must not already
     8     exist.
     9 
    10     If the destination already exists but is not a directory, it may be
    11     overwritten depending on os.rename() semantics.
    12 
    13     If the destination is on our current filesystem, then rename() is used.
    14     Otherwise, src is copied to the destination and then removed. Symlinks are
    15     recreated under the new name if os.rename() fails because of cross
    16     filesystem renames.
    17 
    18     A lot more could be done here...  A look at a mv.c shows a lot of
    19     the issues this implementation glosses over.
    20 
    21     """
    22     real_dst = dst
    23     if os.path.isdir(dst):
    24         if _samefile(src, dst):
    25             # We might be on a case insensitive filesystem,
    26             # perform the rename anyway.
    27             os.rename(src, dst)
    28             return
    29 
    30         real_dst = os.path.join(dst, _basename(src))
    31         if os.path.exists(real_dst):
    32             raise Error("Destination path '%s' already exists" % real_dst)
    33     try:
    34         os.rename(src, real_dst)
    35     except OSError:
    36         if os.path.islink(src):
    37             linkto = os.readlink(src)
    38             os.symlink(linkto, real_dst)
    39             os.unlink(src)
    40         elif os.path.isdir(src):
    41             if _destinsrc(src, dst):
    42                 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
    43             copytree(src, real_dst, symlinks=True)
    44             rmtree(src)
    45         else:
    46             copy2(src, real_dst)
    47             os.unlink(src)
    48     return real_dst
    49 
    50 查看源代码

    10  make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,dry_run=0, owner=None, group=None, logger=None)  #压缩打包

     1 def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
     2                  dry_run=0, owner=None, group=None, logger=None):
     3     """Create an archive file (eg. zip or tar).
     4 
     5     'base_name' is the name of the file to create, minus any format-specific
     6     extension; 'format' is the archive format: one of "zip", "tar", "bztar"
     7     or "gztar".
     8 
     9     'root_dir' is a directory that will be the root directory of the
    10     archive; ie. we typically chdir into 'root_dir' before creating the
    11     archive.  'base_dir' is the directory where we start archiving from;
    12     ie. 'base_dir' will be the common prefix of all files and
    13     directories in the archive.  'root_dir' and 'base_dir' both default
    14     to the current directory.  Returns the name of the archive file.
    15 
    16     'owner' and 'group' are used when creating a tar archive. By default,
    17     uses the current owner and group.
    18     """
    19     save_cwd = os.getcwd()
    20     if root_dir is not None:
    21         if logger is not None:
    22             logger.debug("changing into '%s'", root_dir)
    23         base_name = os.path.abspath(base_name)
    24         if not dry_run:
    25             os.chdir(root_dir)
    26 
    27     if base_dir is None:
    28         base_dir = os.curdir
    29 
    30     kwargs = {'dry_run': dry_run, 'logger': logger}
    31 
    32     try:
    33         format_info = _ARCHIVE_FORMATS[format]
    34     except KeyError:
    35         raise ValueError("unknown archive format '%s'" % format)
    36 
    37     func = format_info[0]
    38     for arg, val in format_info[1]:
    39         kwargs[arg] = val
    40 
    41     if format != 'zip':
    42         kwargs['owner'] = owner
    43         kwargs['group'] = group
    44 
    45     try:
    46         filename = func(base_name, base_dir, **kwargs)
    47     finally:
    48         if root_dir is not None:
    49             if logger is not None:
    50                 logger.debug("changing back to '%s'", save_cwd)
    51             os.chdir(save_cwd)
    52 
    53     return filename
    54 
    55 查看源代码

    base_name:    压缩打包后的文件名或者路径名

    format:          压缩或者打包格式    "zip", "tar", "bztar"or "gztar"

    root_dir :         将哪个目录或者文件打包(也就是源文件)

     1 >>> shutil.make_archive('tarball','gztar',root_dir='copytree_test')
     2 
     3 [root@slyoyo python_test]# ls -l
     4 total 12
     5 drwxr-xr-x. 3 root   root   4096 May 14 19:36 copytree_copy
     6 drwxr-xr-x. 3 root   root   4096 May 14 19:36 copytree_test
     7 -rw-r--r--. 1 root   root      0 May 14 21:12 tarball.tar.gz
     8 -rw-r--r--. 1 python python   79 May 14 05:17 test1
     9 -rw-r--r--. 1 root   root      0 May 14 19:10 test2
    10 
    11 实例
  • 相关阅读:
    正则表达式
    iOS设置图片名称、启动图片、防止TabBar图片和文字渲染
    UIImageView中的UIButton不响应事件解决方案
    iOS 适配https
    【如何快速的开发一个完整的iOS直播app】(美颜篇)
    【如何快速的开发一个完整的iOS直播app】(采集篇)
    【如何快速的开发一个完整的iOS直播app】(播放篇)
    【如何快速的开发一个完整的iOS直播app】(原理篇)
    iOS10字体
    AFN 无网络监控
  • 原文地址:https://www.cnblogs.com/gistwz/p/8125219.html
Copyright © 2020-2023  润新知