小白的Python之路 day5 shutil模块
shutil模块
一、主要用途
高级的文件、文件夹、压缩包 等处理模块
二、常用方法详解
1、shutil.copyfileobj(fsrc, fdst)
功能:把一个文件的内容拷贝到另外一个文件中,可以是部分文件内容。
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)
2、shutil.copyfile(src, dst) #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)
3、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)
4、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
5、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)
6、shutil.copy2(src, dst)
功能:拷贝文件和文件的状态信息
1 def copy2(src, dst): 2 """Copy data and all stat info ("cp -p 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 copystat(src, dst)
7、shutil.copytree(src, dst)
功能:递归的去拷贝文件
1 def copytree(src, dst, symlinks=False, ignore=None): 2 """Recursively copy a directory tree using copy2(). 3 4 The destination directory must not already exist. 5 If exception(s) occur, an Error is raised with a list of reasons. 6 7 If the optional symlinks flag is true, symbolic links in the 8 source tree result in symbolic links in the destination tree; if 9 it is false, the contents of the files pointed to by symbolic 10 links are copied. 11 12 The optional ignore argument is a callable. If given, it 13 is called with the `src` parameter, which is the directory 14 being visited by copytree(), and `names` which is the list of 15 `src` contents, as returned by os.listdir(): 16 17 callable(src, names) -> ignored_names 18 19 Since copytree() is called recursively, the callable will be 20 called once for each directory that is copied. It returns a 21 list of names relative to the `src` directory that should 22 not be copied. 23 24 XXX Consider this example code rather than the ultimate tool. 25 26 """ 27 names = os.listdir(src) 28 if ignore is not None: 29 ignored_names = ignore(src, names) 30 else: 31 ignored_names = set() 32 33 os.makedirs(dst) 34 errors = [] 35 for name in names: 36 if name in ignored_names: 37 continue 38 srcname = os.path.join(src, name) 39 dstname = os.path.join(dst, name) 40 try: 41 if symlinks and os.path.islink(srcname): 42 linkto = os.readlink(srcname) 43 os.symlink(linkto, dstname) 44 elif os.path.isdir(srcname): 45 copytree(srcname, dstname, symlinks, ignore) 46 else: 47 # Will raise a SpecialFileError for unsupported file types 48 copy2(srcname, dstname) 49 # catch the Error from the recursive copytree so that we can 50 # continue with other files 51 except Error, err: 52 errors.extend(err.args[0]) 53 except EnvironmentError, why: 54 errors.append((srcname, dstname, str(why))) 55 try: 56 copystat(src, dst) 57 except OSError, why: 58 if WindowsError is not None and isinstance(why, WindowsError): 59 # Copying file access times may fail on Windows 60 pass 61 else: 62 errors.append((src, dst, str(why))) 63 if errors: 64 raise Error, errors
8、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())
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. 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)
三、压缩包,解压
1、shutil.make_archive((base_name, format, root_dir=None,base_dir=None,verbose=0,dry=0,owner=None,group=None,logger=None)
功能:创建压缩包并且返回文件路径,例如:zip,tar
base_name : 压缩包的文件名,也可以是压缩包的路径。只是文件名,则保存当前目录,否则保存到指定路径。
如:www ==>保存到当前路径
:C:\Users\Administrator\www ===>保存至C:\Users\Administrator\
format:压缩包种类,’zip’,’tar’,’bztar’,’gztar’
root_dir:需要压缩的文件夹路径(默认当前路径)
owner:用户,默认当前用户
group:组,默认当前组
logger:用于记录日志,通常是logging.Logger对象 #还有讲到,后面会补
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
2、zipfile
功能:以zip的形式压缩文件,注意了这个只能压缩文件,不能压缩目录,如果压缩,也只能显示空目录。
1 import zipfile 2 3 # 压缩 4 z = zipfile.ZipFile('qianduoduo.zip', 'w') 5 z.write('info') #写入当前环境变量内的文件 6 z.write('shutil_test.py') 7 z.close() #关闭 8 9 # 解压 10 z = zipfile.ZipFile('qianduoduo.zip', 'r') 11 z.extractall() #解压所有压缩包内的文件 12 z.close()
3、tarfile
功能:以tar的形式打包文件,这边能打包所以文件,包括目录
1 import tarfile 2 3 # 压缩 4 import tarfile 5 tar = tarfile.open("钱多多.tar","w") 6 tar.add("f:haha\钱多多.zip") 7 tar.add("f:haha\钱多多1.tar") 8 tar.close() 9 #解压 10 tar = tarfile.open("钱多多.tar",'r') 11 tar.extractall() #可以添加路径 12 tar.close()
小结:
1、tar打包不会压缩文件,所以文件的大小没有变
2、zip才会压缩,所以压缩后的文件大小会变小
3、一般情况下是先打包再压缩