You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:47:50