Python学习笔记——基础篇第六周——shutil模块
Posted Yared
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习笔记——基础篇第六周——shutil模块相关的知识,希望对你有一定的参考价值。
常用模块之shutil
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中,可以部分内容
1 def copyfileobj(fsrc, fdst, length=16*1024): 2 """copy data from file-like object fsrc to file-like object fdst""" 3 while 1: 4 buf = fsrc.read(length) 5 if not buf: 6 break 7 fdst.write(buf)
shutil.copyfile(src, dst)
拷贝文件
1 def copyfile(src, dst): 2 """Copy data from src to dst""" 3 if _samefile(src, dst): 4 raise Error("`%s` and `%s` are the same file" % (src, dst)) 5 6 for fn in [src, dst]: 7 try: 8 st = os.stat(fn) 9 except OSError: 10 # File most likely does not exist 11 pass 12 else: 13 # XXX What about other special files? (sockets, devices...) 14 if stat.S_ISFIFO(st.st_mode): 15 raise SpecialFileError("`%s` is a named pipe" % fn) 16 17 with open(src, \'rb\') as fsrc: 18 with open(dst, \'wb\') as fdst: 19 copyfileobj(fsrc, fdst)
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
1 def copymode(src, dst): 2 """Copy mode bits from src to dst""" 3 if hasattr(os, \'chmod\'): 4 st = os.stat(src) 5 mode = stat.S_IMODE(st.st_mode) 6 os.chmod(dst, mode)
shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags
1 def copystat(src, dst): 2 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" 3 st = os.stat(src) 4 mode = stat.S_IMODE(st.st_mode) 5 if hasattr(os, \'utime\'): 6 os.utime(dst, (st.st_atime, st.st_mtime)) 7 if hasattr(os, \'chmod\'): 8 os.chmod(dst, mode) 9 if hasattr(os, \'chflags\') and hasattr(st, \'st_flags\'): 10 try: 11 os.chflags(dst, st.st_flags) 12 except OSError, why: 13 for err in \'EOPNOTSUPP\', \'ENOTSUP\': 14 if hasattr(errno, err) and why.errno == getattr(errno, err): 15 break 16 else: 17 raise
shutil.copy(src, dst)
拷贝文件和权限
1 def copy(src, dst): 2 """Copy data and mode bits ("cp src dst"). 3 4 The destination may be a directory. 5 6 """ 7 if os.path.isdir(dst): 8 dst = os.path.join(dst, os.path.basename(src)) 9 copyfile(src, dst) 10 copymode(src, dst)
shutil.copy2(src, dst)
拷贝文件和状态信息
def copy2(src, dst): """Copy data and all stat info ("cp -p src dst"). The destination may be a directory. """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) copyfile(src, dst) copystat(src, dst)
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns(\'*.pyc\', \'tmp*\'))
1 def ignore_patterns(*patterns): 2 """Function that can be used as copytree() ignore parameter. 3 4 Patterns is a sequence of glob-style patterns 5 that are used to exclude files""" 6 def _ignore_patterns(path, names): 7 ignored_names = [] 8 for pattern in patterns: 9 ignored_names.extend(fnmatch.filter(names, pattern)) 10 return set(ignored_names) 11 return _ignore_patterns 12 13 def copytree(src, dst, symlinks=False, ignore=None): 14 """Recursively copy a directory tree using copy2(). 15 16 The destination directory must not already exist. 17 If exception(s) occur, an Error is raised with a list of reasons. 18 19 If the optional symlinks flag is true, symbolic links in the 20 source tree result in symbolic links in the destination tree; if 21 it is false, the contents of the files pointed to by symbolic 22 links are copied. 23 24 The optional ignore argument is a callable. If given, it 25 is called with the `src` parameter, which is the directory 26 being visited by copytree(), and `names` which is the list of 27 `src` contents, as returned by os.listdir(): 28 29 callable(src, names) -> ignored_names 30 31 Since copytree() is called recursively, the callable will be 32 called once for each directory that is copied. It returns a 33 list of names relative to the `src` directory that should 34 not be copied. 35 36 XXX Consider this example code rather than the ultimate tool. 37 38 """ 39 names = os.listdir(src) 40 if ignore is not None: 41 ignored_names = ignore(src, names) 42 else: 43 ignored_names = set() 44 45 os.makedirs(dst) 46 errors = [] 47 for name in names: 48 if name in ignored_names: 49 continue 50 srcname = os.path.join(src, name) 51 dstname = os.path.join(dst, name) 52 try: 53 if symlinks and os.path.islink(srcname): 54 linkto = os.readlink(srcname) 55 os.symlink(linkto, dstname) 56 elif os.path.isdir(srcname): 57 copytree(srcname, dstname, symlinks, ignore) 58 else: 59 # Will raise a SpecialFileError for unsupported file types 60 copy2(srcname, dstname) 61 # catch the Error from the recursive copytree so that we can 62 # continue with other files 63 except Error, err: 64 errors.extend(err.args[0]) 65 except EnvironmentError, why: 66 errors.append((srcname, dstname, str(why))) 67 try: 68 copystat(src, dst) 69 except OSError, why: 70 if WindowsError is not None and isinstance(why, WindowsError): 71 # Copying file access times may fail on Windows 72 pass 73 else: 74 errors.append((src, dst, str(why))) 75 if errors: 76 raise Error, errors
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
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 os.listdir, os.remove, or os.rmdir; 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 try: 19 if os.path.islink(path): 20 # symlinks to directories are forbidden, see bug #1669 21 raise OSError("Cannot call rmtree on a symbolic link") 22 except OSError: 23 onerror(os.path.islink, path, sys.exc_info()) 24 # can\'t continue even if onerror hook returns 25 return 26 names = [] 27 try: 28 names = os.listdir(path) 29 except os.error, err: 30 onerror(os.listdir, path, sys.exc_info()) 31 for name in names: 32 fullname = os.path.join(path, name) 33 try: 34 mode = os.lstat(fullname).st_mode 35 except os.error: 36 mode = 0 37 if stat.S_ISDIR(mode): 38 rmtree(fullname, ignore_errors, onerror) 39 else: 40 try: 41 os.remove(fullname) 42 except os.error, err: 43 onerror(os.remove, fullname, sys.exc_info()) 44 try: 45 os.rmdir(path) 46 except os.error: 47 onerror(os.rmdir, path, sys.exc_info())
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. 4 5 If the destination is a directory or a symlink to a directory, the source 6 is moved inside the directory. The destination path must not already 7 exist. 8 9 If the destination already exists but is not a directory, it may be 10 overwritten depending on os.rename() semantics. 11 12 If the destination is on our current filesystem, then rename() is used. 13 Otherwise, src is copied to the destination and then removed. 14 A lot more could be done here... A look at a mv.c shows a lot of 15 the issues this implementation glosses over. 16 17 """ 18 real_dst = dst 19 if os.path.isdir(dst): 20 if _samefile(src, dst): 21 # We might be on a case insensitive filesystem, 22 # perform the rename anyway. 23 os.rename(src, dst) 24 return 25 26 real_dst = os.path.join(dst, _basename(src)) 27 if os.path.exists(real_dst): 28 raise Error, "Destination path \'%s\' already exists" % real_dst 29 try: 30 os.rename(src, real_dst) 31 except OSError: 32 if os.path.isdir(src): 33 if _destinsrc(src, dst): 34 raise Error, "Cannot move a directory \'%s\' into itself \'%s\'." % (src, dst) 35 copytree(src, real_dst, symlinks=True) 36 rmtree(src) 37 else: 38 copy2(src, real_dst) 39 os.unlink(src)
#运维时做备份时会用到压缩
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录 import shutil ret = shutil.make_archive("wwwwwwwwww", \'gztar\', root_dir=\'/Users/wupeiqi/Downloads/test\') #将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录 import shutil ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", \'gztar\', root_dir=\'/Users/wupeiqi/Downloads/test\')
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
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
1 import zipfile 2 3 # 压缩 4 z = zipfile.ZipFile(\'laxi.zip\', \'w\') 5 z.write(\'a.log\') 6 z.write(\'data.data\') 7 z.close() 8 9 # 解压 10 z = zipfile.ZipFile(\'laxi.zip\', \'r\') 11 z.extractall() 12 z.close()
1 import tarfile 2 3 # 压缩 4 tar = tarfile.open(\'your.tar\',\'w\') 5 tar.add(\'/Users/wupeiqi/PycharmProjects/bbs2.zip\', arcname=\'bbs2.zip\') 6 tar.add(\'/Users/wupeiqi/PycharmProjects/cmdb.zip\', arcname=\'cmdb.zip\') 7 tar.close() 8 9 # 解压 10 tar = tarfile.open(\'your.tar\',\'r\') 11 tar.extractall() # 可设置解压地址 12 tar.close()
1 class ZipFile(object): 2 """ Class with methods to open, read, write, close, list zip files. 3 4 z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False) 5 6 file: Either the path to the file, or a file-like object. 7 If it is a path, the file will be opened and closed by ZipFile. 8 mode: The mode can be either read "r", write "w" or append "a". 9 compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib). 10 allowZip64: if True ZipFile will create files with ZIP64 extensions when 11 needed, otherwise it will raise an exception when this would 12 be necessary. 13 14 """ 15 16 fp = None # Set here since __del__ checks it 17 18 def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False): 19 """Open the ZIP file with mode read "r", write "w" or append "a".""" 20 if mode not in ("r", "w", "a"): 21 raise RuntimeError(\'ZipFile() requires mode "r", "w", or "a"\') 22 23 if compression == ZIP_STORED: 24 pass 25 elif compression == ZIP_DEFLATED: 26 if以上是关于Python学习笔记——基础篇第六周——shutil模块的主要内容,如果未能解决你的问题,请参考以下文章
Python学习笔记——基础篇第六周——Subprocess模块