shutil.copy vs copyfile vs copytree:Python文件复制函数全对比(附常见错误修复)
shutil.copy vs copyfile vs copytreePython文件复制函数全对比附常见错误修复在Python项目中处理文件操作时shutil模块是开发者最常用的工具之一。这个标准库模块提供了多种文件复制方法但很多开发者在使用过程中常常会遇到各种错误尤其是PermissionError: [Errno 13] Permission denied这类权限问题。本文将深入分析shutil.copy、shutil.copyfile和shutil.copytree三个核心函数的区别帮助你在实际项目中做出正确选择。1. 核心函数对比与适用场景1.1 函数定义与基本用法shutil模块提供了三个主要的文件复制函数它们在参数要求和功能上有所不同import shutil # 1. shutil.copy(src, dst, *, follow_symlinksTrue) shutil.copy(source.txt, destination_folder/) # dst可以是目录 shutil.copy(source.txt, destination_folder/new_name.txt) # dst也可以是文件路径 # 2. shutil.copyfile(src, dst, *, follow_symlinksTrue) shutil.copyfile(source.txt, destination.txt) # src和dst都必须是文件路径 # 3. shutil.copytree(src, dst, symlinksFalse, ignoreNone, copy_functioncopy2, ignore_dangling_symlinksFalse) shutil.copytree(source_dir, destination_dir) # 复制整个目录树1.2 参数要求对比函数src类型dst类型复制内容保留元数据符号链接处理copy文件文件/目录文件内容部分可配置copyfile文件文件文件内容无可配置copytree目录目录目录树全部可配置1.3 性能差异在大多数情况下copyfile是最快的因为它只复制文件内容而不处理元数据。copy会额外复制一些权限信息而copytree由于需要递归处理整个目录结构性能开销最大。2. 常见错误与解决方案2.1 PermissionError: [Errno 13] Permission denied这是最常见的错误之一通常由以下原因导致目标路径是目录但使用了copyfile# 错误示例 shutil.copyfile(source.txt, destination_folder/) # 会抛出PermissionError # 正确做法 shutil.copy(source.txt, destination_folder/) # 使用copy目标文件没有写入权限# 解决方案检查并修改权限 import os if not os.access(destination.txt, os.W_OK): os.chmod(destination.txt, 0o644) # 修改权限目标路径不存在# 先创建目录结构 os.makedirs(os.path.dirname(destination.txt), exist_okTrue)2.2 SameFileError当源文件和目标文件路径相同时会抛出此错误# 错误示例 shutil.copyfile(source.txt, source.txt) # 会抛出SameFileError # 解决方案比较路径是否相同 src source.txt dst source.txt if os.path.abspath(src) ! os.path.abspath(dst): shutil.copyfile(src, dst)2.3 FileNotFoundError源文件不存在时会出现此错误# 防御性编程 if os.path.exists(source.txt): shutil.copyfile(source.txt, destination.txt) else: print(源文件不存在)3. 高级用法与最佳实践3.1 自定义复制函数copytree允许你指定自定义的复制函数def my_copy_function(src, dst): print(fCopying {src} to {dst}) return shutil.copy2(src, dst) # 使用copy2保留更多元数据 shutil.copytree(src_dir, dst_dir, copy_functionmy_copy_function)3.2 忽略特定文件使用ignore参数可以过滤不需要复制的文件def ignore_pyc_files(dirname, filenames): return [name for name in filenames if name.endswith(.pyc)] shutil.copytree(src_dir, dst_dir, ignoreignore_pyc_files)3.3 处理符号链接默认情况下copytree会跟随符号链接。要改变这一行为# 不跟随符号链接而是复制链接本身 shutil.copytree(src_dir, dst_dir, symlinksTrue)4. 实际项目中的选择建议4.1 何时使用copy需要简单复制单个文件目标路径可能是目录或文件需要保留部分文件元数据如权限# 典型场景将配置文件复制到用户目录 config_file app_config.ini user_config_dir os.path.expanduser(~/.myapp) shutil.copy(config_file, user_config_dir)4.2 何时使用copyfile需要最高性能的文件复制明确知道目标路径必须是文件不需要保留文件权限等元数据# 典型场景处理大量临时文件 for i in range(1000): shutil.copyfile(ftemplate_{i}.tmp, foutput_{i}.tmp)4.3 何时使用copytree需要复制整个目录结构需要保留完整的文件元数据可能需要自定义复制过程或过滤文件# 典型场景项目部署时复制静态资源 shutil.copytree(static_files, deploy/static, ignoreignore_pyc_files)5. 性能优化技巧5.1 大文件复制优化对于大文件可以使用更底层的文件操作def copy_large_file(src, dst, buffer_size1024*1024): with open(src, rb) as fsrc: with open(dst, wb) as fdst: while True: buf fsrc.read(buffer_size) if not buf: break fdst.write(buf)5.2 并行复制对于大量文件可以使用多线程加速from concurrent.futures import ThreadPoolExecutor def batch_copy(file_pairs): with ThreadPoolExecutor() as executor: executor.map(lambda pair: shutil.copyfile(*pair), file_pairs)5.3 增量复制只复制修改过的文件def sync_files(src_dir, dst_dir): for root, dirs, files in os.walk(src_dir): rel_path os.path.relpath(root, src_dir) dst_root os.path.join(dst_dir, rel_path) for file in files: src_file os.path.join(root, file) dst_file os.path.join(dst_root, file) if not os.path.exists(dst_file) or \ os.path.getmtime(src_file) os.path.getmtime(dst_file): shutil.copy2(src_file, dst_file)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2441516.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!