shutil 模块介绍 shutil 模块是 Python 内置的对文件、目录、压缩文件进行高级操作的模块,该模块对文件的复制、删除和压缩等操作都提供了非常方便的支持。 在使用 shutil 模块时,不能复制所有文件的元数据。在 POSIX 平台上不能复制文件的所有者和组、以及访问控制表;在 macOS 中不能复制文件类型和创建者;在 Windows 中不能复制文件的所有者、访问控制列表和备用数据流。 shutil 模块是 Python 内置,直接导入即可使用。 chown:更改指定路径的所有者用户(组) 函数原型:shutil.chown(path, user=None, group=None),参数含义如下: path:指定要操作的路径 user:指定所有者,可以是系统用户名或者 UID,如果用户不存在则报错 "没有此用户" group:表示组 该方法只适用于 Unix 系统。 >>> import shutil >>> import pwd # 该模块需要在 Unix 上使用 >>> import os >>> >>> uid = os.stat("/root").st_uid >>> pwd.getpwuid(uid) pwd.struct_passwd(pw_name='root', pw_passwd='x', pw_uid=0, pw_gid=0, pw_gecos='root', pw_dir='/root', pw_shell='/bin/bash') >>> # 可以通过 shutil 进行调用,然后再进行查看 copy:复制文件或目录 copy 函数可以将一个文件复制为另一个文件(或另一个目录中)。 函数原型:shutil.copy(src, dst, *, follow_symlinks=True),参数含义如下: src:表示文件路径的字符串,表示源文件(注意:必须是文件,如果是目录则报出权限错误) dst:表示文件或目录路径的字符串,如果是一个已经存在的目录,那么会将 src 拷贝到该目录中;否则会创建相应的文件。 follow_symlinks:表示是否遵循符号链接,默认为 True。如果为 True 则赋值文件,为 False、并且 src 为软连接,则创建一个新的软连接 该函数会返回目标路径,即新创建的文件的路径。 import shutil # 如果 test 存在并且是目录,那么会将 1.txt 拷贝到 test 中 shutil.copy("1.txt", "test") # 如果 test 不存在,那么会创建一个名为 test 的文件,内容和 1.txt 一致 # 如果 test 存在并且不是目录,那么会把原来的文件覆盖掉(需要具备写权限,否则报错 PermissionError) shutil.copy("1.txt", "test") 使用 copy 复制文件时,文件的元信息(创建时间、修改时间)不会被保留,相当于创建了新文件。如果要保留文件的元信息,需要使用 copy2 函数(和 copy 函数用法一致,区别就是前者不保留文件元信息、后者会保留)。 copyfile:复制文件内容 参数和 copy、copy2 完全一致,只不过 copyflle 的 dst 如果已存在,那么必须是文件。 # 如果 test 存在并且是目录,会报错:PermissionError: [Errno 13] Permission denied: 'test' shutil.copyfile("1.txt", "test") # 如果 test 不存在,那么会创建一个名为 test 的文件,内容和 1.txt 一致 # 如果 test 存在并且不是目录,那么会把原来的文件覆盖掉 shutil.copyfile("1.txt", "test") 比较简单,可以自己试一下,所以 copy 要比 copyfile 更高级一些。 使用 copyfile 同样需要写权限,并且 src 和 dst 不能是同一个文件,否则会报错:SameFileError。 比较简单,可以自己试一下,所以 copy 要比 copyfile 更高级一些。并且除了 copyfile,还有一个更加低级的 copyfileobj。copyfileobj 也是拷贝,接收三个参数:fsrc、fdst、length,前两个参数和 copy 类似,只不过 fsrc 和 fdst 都必须是打开的文件对象,从名字上也能看出。至于第三个参数 length 表示缓冲区,如果为负数表示直接复制,默认是 16 * 1024 字节。 # 这么写会报错:AttributeError: 'str' object has no attribute 'read' # 因为接收的是文件对象,会调用 read 进行读取 shutil.copyfile("1.txt", "test") 所以 src 是一个读模式打开的文件,dst 是一个写模式打开的文件,然后将 src 拷贝到 dst 中,这个函数更加低级。我们可以使用 io.StringIO 演示一下: import shutil from io import StringIO buf1 = StringIO() buf2 = StringIO() # buf1 里面写入一些内容 buf1.write("古明地觉") # 调整指针,移到开头,否则读取不到内容 buf1.seek(0) # 将 buf1 拷贝到 buf2 中 shutil.copyfileobj(buf1, buf2) # 查看 buf2 中的内容 print(buf2.getvalue()) # 古明地觉 虽然 copyfileobj 比较低级,但是它的速度也更快。当复制大文件时,采用 copyfileobj 会更有效率,复制小文件则使用 copyfile 会更快一些。 copymode:复制权限位 参数和 copy 函数也完全相同,只不过它是将一个文件的权限复制给另一个文件。比如 A 文件是只读,那么复制给 B 之后 B 也是只读,但是 A 的内容不会复制给 B,因为 copymode 只是复制权限。 除了 copymode 还有一个 copystat,参数也是一样的,只不过它除了复制权限之外还复制最后访问时间、最后修改时间等元信息,可以自己试一下这两个函数。 copytree:递归复制整个目录树 copytree 方法可以递归复制整个目录,并返回目标目录的路径,语法格式如下: copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False) 参数含义如下: src:表示路径的字符串,必须是一个已存在的目录,不能是文件 dst:表示路径的字符串,必须是一个不存在的目录,否则报错:FileExistsError symlinks:是否遵循符号链接,默认为 True。如果为 True,表示复制文件,如果为 False,那么当 src 为软连接、则创建一个新的软连接 ignore:可选参数,表示一个可调用对象,该可调用对象接收两个参数,第一个参数是要复制的目录名,第二个参数是要复制的目录里面的所有目录或文件的名称(不递归显示子目录中,只显示内部一层) copy_function:从默认值可以看出,表示拷贝函数,这里采用的是 copy2,会将文件的元信息也保留 ignore_dangling_symlinks:是否忽略 symlinks,如果值为 True 则忽略,值为 False,那么当文件不存在时则产生异常。对于不支持 os.symlink() 的平台,此参数无任何影响 比较简单,可以自己尝试一下。 disk_usage:获取磁盘的使用情况 该函数接收一个参数 path 表示路径,会自动获取改路径所在磁盘的使用情况:总空间、已使用空间和空闲空间,以字节为单位。 在 Windows 中 path 必须是一个目录,在 Unix 中可以是目录也可以是文件。 import shutil disk_F = shutil.disk_usage("F:") print(disk_F) # usage(total=1000202039296, used=447226023936, free=552976015360) print(disk_F.total / 1024 / 1024 / 1024) # 931.5107383728027 print(disk_F.used / 1024 / 1024 / 1024) # 416.51169204711914 print(disk_F.free / 1024 / 1024 / 1024) # 514.9990463256836 get_archive_formats:获取支持的压缩格式 get_archive_formats 函数可以返回当前系统支持的压缩格式列表: import shutil from pprint import pprint pprint(shutil.get_archive_formats()) """ [('bztar', "bzip2'ed tar-file"), ('gztar', "gzip'ed tar-file"), ('tar', 'uncompressed tar file'), ('xztar', "xz'ed tar-file"), ('zip', 'ZIP file')] """ 既然有压缩,那么就有解压缩,get_unpack_formats 函数可以返回当前系统支持的解压缩格式列表: import shutil from pprint import pprint pprint(shutil.get_unpack_formats()) """ [('bztar', ['.tar.bz2', '.tbz2'], "bzip2'ed tar-file"), ('gztar', ['.tar.gz', '.tgz'], "gzip'ed tar-file"), ('tar', ['.tar'], 'uncompressed tar file'), ('xztar', ['.tar.xz', '.txz'], "xz'ed tar-file"), ('zip', ['.zip'], 'ZIP file')] """ get_terminal_size:获取终端窗口的大小 get_terminal_size 函数可以获取终端窗口的大小,语法格式如下: shutil.get_terminal_size(fallback=(80, 24)) 如果系统不支持查询,或者未连接到终端,那么返回 (80, 24),表示列数和行数。 import shutil print(shutil.get_terminal_size()) # os.terminal_size(columns=80, lines=24) ignore_patterns:提供 glob 通配符功能 ignore_patterns 是一个工厂函数,用于为 shutil.copytree 的 ignore 参数提供值,该值在复制的过程中会被忽略。比如:我们在使用 shutil.copytree 的时候不想复制 .txt 结尾和 bak 开头的文件,那么就可以这么做: import shutil shutil.copytree("test1", "test2", ignore=shutil.ignore_patterns("*.go", "bak*")) make_archive:创建压缩文件并返回文件路径 通过 make_archive 可以创建压缩文件,语法格式如下: shutil.make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None) 参数含义如下: base_name:表示压缩包的文件名(不包含扩展名),也可以包含路径,如果只写文件名则保存到当前目录,否则保存到指定路径 format:表示压缩包格式,如 zip、tar、bztar、gztar 等 root_dir:表示将要被压缩的目录路径,默认是当前目录 base_dir:表示开始压缩的目录,即压缩文件中所有文件和目录的公共前缀,默认为当前目录 verbose:已弃用 dry_run:表示是否创建存档,如果 dry_run 为 True,则不会创建存档,但会将执行的操作记录到 logger owner:可选参数,用于指定用户,默认为当前用户 group:可选参数,用于指定组,默认为当前组 logger:用于记录日志,通常为 logging.Logger 对象 make_archive 函数依赖于 zipfile 和 tarfile 模块。 import shutil shutil.make_archive("tmp", "zip", root_dir=r"F:\动漫\缘之空") 之后会在当前目录中出现一个 tmp.zip,目录 r"F:\动漫\缘之空" 里面的所有内容都会被压缩到里面。 有压缩,那么自然有解压缩,shutil.unpack_archive(filename, extract_dir=None, format=None): filename:解压缩文件的路径 extract_dir:解压到哪个目录,未指定则解压到当前目录 format:表示压缩包的格式,如:zip、bztar、gztar 等等,如果没有提供那么则根据压缩文件扩展名进行推断 该方法同样依赖于 zipfile 和 tarfile 两个模块。 move:移动文件和目录 move 方法用于将文件或目录移动到目标目录,如果移动到了不同的文件系统中,那么移动将会变成复制。参数如下: src:无需解释 dst:无需解释 copy_function:默认是 copy2 举个栗子: import shutil # 将 F 盘的 code1 目录移动到 code2 目录 shutil.move(r"F:\code1", r"F:\code2") rmtree:删除整个目录树 rmtree 函数用于删除整个目录树,参数如下: path:表示路径的字符串,必须是一个目录,不能是文件 ignore_errors:默认为 False,表示是否忽略删除中出现的错误。如果为 True 表示忽略、为 False 表示不忽略 onerror:一个错误处理函数,接收三个参数:func(引发异常的函数)、path(传递到函数中的路径)、excinfo(返回的异常信息)。如果 onerror 被省略,那么当发生错误时会给出提示 import shutil shutil.rmtree(r"F:\code1") which:获取可执行文件的路径 我们在终端中输入 python 的时候会自动进入交互式解释器中,这是因为在环境变量中配置了 python 解释器的路径,而通过 which 函数可以获取相应的路径。该函数接收参数如下: cmd:相关命令 mode:用于指定需要传递的权限掩码,默认为 os.F_OK | os.X_OK,表示测试路径是否存在、并且是否可执行 path,默认为 None,表示查找 cmd 命令的路径。如果不指定则在环境变量中查找,指定了则在指定的路径参数查找。但是注意:不管指没指定,当前目录始终会被添加到搜索路径中 import shutil print(shutil.which("python")) # C:\python38\python.EXE print(shutil.which("go")) # C:\Go\bin\go.EXE print(shutil.which("lua")) # C:\lua\lua.EXE print(shutil.which("gcc")) # C:\MinGW\bin\gcc.EXE print(shutil.which("xxxxx")) # None 小结 以上就是 shutil 的一些用法,可以说在对文件处理方面做了很多工作,在工作中不妨多使用以下。尤其是在涉及文件拷贝的时候,真的非常方便。