如何使distutils.dir_util.copy_tree函数遇错误时持续执行?
解决
copy_tree遇错即停,实现忽略错误继续复制的方案 我明白你的痛点——用dir_util.copy_tree的时候,只要有一个文件或目录复制失败,整个操作就直接终止了,没法跳过错误继续处理剩下的内容。确实这个工具函数的文档比较匮乏,而且默认就是“失败即停止”的设计逻辑,所以得换个思路来实现需求。
核心问题在于copy_tree是一次性处理整个目录树的原子操作,一旦中间出问题就会抛出异常并停止。要实现“忽略错误继续复制”,我们需要手动遍历目录树,逐个处理每个文件的复制,给每个复制操作单独加异常捕获,这样某个文件失败了,只会记录日志,不会影响后续的文件处理。
下面是修改后的完整函数,保留了你原有的日志逻辑,同时实现了错误忽略的功能:
import os import shutil import datetime # 假设lg和log是你已定义的日志工具 def copyFilesAccross(source, destination, upd, file): lg.set_verbosity(lg.INFO) lg.set_threshold(lg.INFO) startTime = datetime.datetime.now() log(0, "copyFilesAccross: Copying files ...", file) # 遍历源目录下的所有层级的文件和目录 for root, dirs, files in os.walk(source): # 计算当前目录相对于源目录的路径,用来映射到目标目录 relative_path = os.path.relpath(root, source) target_dir = os.path.join(destination, relative_path) # 先创建目标目录(如果不存在) try: os.makedirs(target_dir, exist_ok=True) except OSError as e: log(1, f"copyFilesAccross: Failed to create directory {target_dir} with error: {str(e)}", file) # 创建目录失败,跳过这个目录下的所有文件,继续处理下一个目录 continue # 处理当前目录下的每个文件 for filename in files: source_file_path = os.path.join(root, filename) target_file_path = os.path.join(target_dir, filename) try: # 根据upd参数决定是否只更新(复制 newer 的文件) if upd: # 目标文件不存在,或者源文件比目标文件新,才复制 if not os.path.exists(target_file_path) or os.path.getmtime(source_file_path) > os.path.getmtime(target_file_path): shutil.copy2(source_file_path, target_file_path) log(0, f"copyFilesAccross: Copied {source_file_path} to {target_file_path}", file) else: # 不更新,直接复制覆盖 shutil.copy2(source_file_path, target_file_path) log(0, f"copyFilesAccross: Copied {source_file_path} to {target_file_path}", file) except OSError as e: log(1, f"copyFilesAccross: Failed to copy {source_file_path} to {target_file_path} with error: {str(e)}", file) # 跳过当前失败的文件,继续处理下一个 continue except Exception as e: # 捕获其他意料之外的异常,避免程序中断 log(1, f"copyFilesAccross: Unexpected error copying {source_file_path} to {target_file_path}: {str(e)}", file) continue log(0, f"copyFilesAccross: Operation has completed successfully in: {datetime.datetime.now() - startTime}", file)
关键改动说明:
- 用
os.walk替代dir_util.copy_tree,手动遍历整个目录树,实现细粒度的控制 - 每个目录的创建、每个文件的复制都单独加了异常捕获,出错时记录日志并继续执行
- 用
shutil.copy2复制文件,它会保留文件的元数据(比如修改时间),和copy_tree的默认行为一致 - 实现了
upd参数的逻辑:当upd=True时,只复制目标不存在或源文件更新的文件,和原函数的update参数功能匹配
这样修改后,就算某个文件或目录复制失败,程序也会继续处理剩下的内容,完美解决你遇到的问题。
内容的提问来源于stack exchange,提问作者Alex R.
相关产品推荐
相关产品推荐

