admin管理员组

文章数量:1636917

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 notbuf:7 break

8 fdst.write(buf)9

10 #注意! 在其中fsrc,fdst都是文件对象,都需要打开后才能进行复制操作

11 importshutil12 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 new5 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 exceptOSError:15 #File most likely does not exist

16 pass

17 else:18 #XXX What about other special files? (sockets, devices...)

19 ifstat.S_ISFIFO(st.st_mode):20 raise SpecialFileError("`%s` is a named pipe" %fn)21

22 if not follow_symlinks andos.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 returndst29

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 only5 if both `src` and `dst` are symlinks. If `lchmod` isn't available6 (e.g. Linux) this method does nothing.7

8 """

9 if not follow_symlinks and os.path.islink(src) andos.path.islink(dst):10 if hasattr(os, 'lchmod'):11 stat_func, chmod_func =os.lstat, os.lchmod12 else:13 return

14 elif hasattr(os, 'chmod'):15 stat_func, chmod_func =os.stat, os.chmod16 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 only5 if both `src` and `dst` are symlinks. If `lchmod` isn't available6 (e.g. Linux) this method does nothing.7

8 """

9 if not follow_symlinks and os.path.islink(src) andos.path.islink(dst):10 if hasattr(os, 'lchmod'):11 stat_func, chmod_func =os.lstat, os.lchmod12 else:13 return

14 elif hasattr(os, 'chmod'):15 stat_func, chmod_func =os.stat, os.chmod16 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 and5 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) andos.path.islink(dst))13 iffollow:14 #use the real function if it exists

15 deflookup(name):16 returngetattr(os, name, _nop)17 else:18 #use the real function only if it exists

19 #*and* it supports follow_symlinks

20 deflookup(name):21 fn =getattr(os, name, _nop)22 if fn inos.supports_follow_symlinks:23 returnfn24 return_nop25

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 exceptNotImplementedError: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 exceptOSError 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. This7 resembles GNU's "cp -P src dst".8

9 If source and destination are the same file, a SameFileError will be10 raised.11

12 """

13 ifos.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 returndst18

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's3 destination."4

5 The destination may be a directory.6

7 If follow_symlinks is false, symlinks won't be followed. This8 resembles GNU's "cp -P src dst".9

10 """

11 ifos.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 returndst16

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 the9 source tree result in symbolic links in the destination tree; if10 it is false, the contents of the files pointed to by symbolic11 links are copied. If the file pointed by the symlink doesn't12 exist, an exception will be added in the list of errors raised in13 an Error exception at the end of the copy process.14

15 You can set the optional ignore_dangling_symlinks flag to true if you16 want to silence this exception. Notice that this has no effect on17 platforms that don't support os.symlink.18

19 The optional ignore argument is a callable. If given, it20 is called with the `src` parameter, which is the directory21 being visited by copytree(), and `names` which is the list of22 `src` contents, as returned by os.listdir():23

24 callable(src, names) -> ignored_names25

26 Since copytree() is called recursively, the callable will be27 called once for each directory that is copied. It returns a28 list of names relative to the `src` directory that should29 not be copied.30

31 The optional copy_function argument is a callable that will be used32 to copy each file. It will be called with the source path and the33 destination path as arguments. By default, copy2() is used, but any34 function that supports the same signature (like copy()) can be used.35

36 """

37 names =os.listdir(src)38 if ignore is notNone:39 ignored_names =ignore(src, names)40 else:41 ignored_names =set()42

43 os.makedirs(dst)44 errors =[]45 for name innames:46 if name inignored_names:47 continue

48 srcname =os.path.join(src, name)49 dstname =os.path.join(dst, name)50 try:51 ifos.path.islink(srcname):52 linkto =os.readlink(srcname)53 ifsymlinks: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=notsymlinks)59 else:60 #ignore dangling symlink if the flag is on

61 if not os.path.exists(linkto) andignore_dangling_symlinks:62 continue

63 #otherwise let the copy occurs. copy2 will raise an error

64 ifos.path.isdir(srcname):65 copytree(srcname, dstname, symlinks, ignore,66 copy_function)67 else:68 copy_function(srcname, dstname)69 elifos.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 exceptError as err:77 errors.extend(err.args[0])78 exceptOSError as why:79 errors.append((srcname, dstname, str(why)))80 try:81 copystat(src, dst)82 exceptOSError as why:83 #Copying file access times may fail on Windows

84 if getattr(why, 'winerror', None) isNone:85 errors.append((src, dst, str(why)))86 iferrors:87 raiseError(errors)88 returndst89

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 the9 source tree result in symbolic links in the destination tree; if10 it is false, the contents of the files pointed to by symbolic11 links are copied. If the file pointed by the symlink doesn't12 exist, an exception will be added in the list of errors raised in13 an Error exception at the end of the copy process.14

15 You can set the optional ignore_dangling_symlinks flag to true if you16 want to silence this exception. Notice that this has no effect on17 platforms that don't support os.symlink.18

19 The optional ignore argument is a callable. If given, it20 is called with the `src` parameter, which is the directory21 being visited by copytree(), and `names` which is the list of22 `src` contents, as returned by os.listdir():23

24 callable(src, names) -> ignored_names25

26 Since copytree() is called recursively, the callable will be27 called once for each directory that is copied. It returns a28 list of names relative to the `src` directory that should29 not be copied.30

31 The optional copy_function argument is a callable that will be used32 to copy each file. It will be called with the source path and the33 destination path as arguments. By default, copy2() is used, but any34 function that supports the same signature (like copy()) can be used.35

36 """

37 names =os.listdir(src)38 if ignore is notNone:39 ignored_names =ignore(src, names)40 else:41 ignored_names =set()42

43 os.makedirs(dst)44 errors =[]45 for name innames:46 if name inignored_names:47 continue

48 srcname =os.path.join(src, name)49 dstname =os.path.join(dst, name)50 try:51 ifos.path.islink(srcname):52 linkto =os.readlink(srcname)53 ifsymlinks: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=notsymlinks)59 else:60 #ignore dangling symlink if the flag is on

61 if not os.path.exists(linkto) andignore_dangling_symlinks:62 continue

63 #otherwise let the copy occurs. copy2 will raise an error

64 ifos.path.isdir(srcname):65 copytree(srcname, dstname, symlinks, ignore,66 copy_function)67 else:68 copy_function(srcname, dstname)69 elifos.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 exceptError as err:77 errors.extend(err.args[0])78 exceptOSError as why:79 errors.append((srcname, dstname, str(why)))80 try:81 copystat(src, dst)82 exceptOSError as why:83 #Copying file access times may fail on Windows

84 if getattr(why, 'winerror', None) isNone:85 errors.append((src, dst, str(why)))86 iferrors:87 raiseError(errors)88 returndst89

90 #version vulnerable to race conditions

91

92 查看源代码

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

1 def rmtree(path, ignore_errors=False, οnerrοr=None):2 """Recursively delete a directory tree.3

4 If ignore_errors is set, errors are ignored; otherwise, if onerror5 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; and8 exc_info is a tuple returned by sys.exc_info(). If ignore_errors9 is false and onerror is None, an exception is raised.10

11 """

12 ifignore_errors:13 def onerror(*args):14 pass

15 elif onerror isNone: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 ifisinstance(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 exceptException:27 onerror(os.lstat, path, sys.exc_info())28 return

29 try:30 fd =os.open(path, os.O_RDONLY)31 exceptException:32 onerror(os.lstat, path, sys.exc_info())33 return

34 try:35 ifos.path.samestat(orig_st, os.fstat(fd)):36 _rmtree_safe_fd(fd, path, onerror)37 try:38 os.rmdir(path)39 exceptOSError: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 exceptOSError: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_functions55

56 查看源代码

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

1 defmove(src, dst):2 """Recursively move a file or directory to another location. This is3 similar to the Unix "mv" command. Return the file or directory's4 destination.5

6 If the destination is a directory or a symlink to a directory, the source7 is moved inside the directory. The destination path must not already8 exist.9

10 If the destination already exists but is not a directory, it may be11 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 are15 recreated under the new name if os.rename() fails because of cross16 filesystem renames.17

18 A lot more could be done here... A look at a mv.c shows a lot of19 the issues this implementation glosses over.20

21 """

22 real_dst =dst23 ifos.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 ifos.path.exists(real_dst):32 raise Error("Destination path '%s' already exists" %real_dst)33 try:34 os.rename(src, real_dst)35 exceptOSError:36 ifos.path.islink(src):37 linkto =os.readlink(src)38 os.symlink(linkto, real_dst)39 os.unlink(src)40 elifos.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 returnreal_dst49

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-specific6 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 the10 archive; ie. we typically chdir into 'root_dir' before creating the11 archive. 'base_dir' is the directory where we start archiving from;12 ie. 'base_dir' will be the common prefix of all files and13 directories in the archive. 'root_dir' and 'base_dir' both default14 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 notNone:21 if logger is notNone:22 logger.debug("changing into '%s'", root_dir)23 base_name =os.path.abspath(base_name)24 if notdry_run:25 os.chdir(root_dir)26

27 if base_dir isNone:28 base_dir =os.curdir29

30 kwargs = {'dry_run': dry_run, 'logger': logger}31

32 try:33 format_info =_ARCHIVE_FORMATS[format]34 exceptKeyError: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] =val40

41 if format != 'zip':42 kwargs['owner'] =owner43 kwargs['group'] =group44

45 try:46 filename = func(base_name, base_dir, **kwargs)47 finally:48 if root_dir is notNone:49 if logger is notNone:50 logger.debug("changing back to '%s'", save_cwd)51 os.chdir(save_cwd)52

53 returnfilename54

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:36copytree_copy6 drwxr-xr-x. 3 root root 4096 May 14 19:36copytree_test7 -rw-r--r--. 1 root root 0 May 14 21:12tarball.tar.gz8 -rw-r--r--. 1 python python 79 May 14 05:17test19 -rw-r--r--. 1 root root 0 May 14 19:10test210

11 实例

本文标签: 模块shutilpythonPython