Python如何在大型数据集中快速定位并复制指定ID的jpg图像文件
现有代码核心问题
你当前的代码性能极差、且存在逻辑错误,核心问题如下:
- 重复读取CSV文件:每遍历1个图像文件就会完整读取1次1000条ID的CSV文件,200万张图就要执行200万次CSV读取操作,磁盘IO开销占了99%以上的运行时间,是最大的性能瓶颈
- 时间复杂度极高:匹配逻辑是每个文件遍历全部1000条ID逐一判断,总时间复杂度为O(200万 * 1000),存在巨量的冗余计算
- 路径拼接错误:
- 拼接源文件路径时没有带上
os.walk返回的当前子目录路径root,无法识别子目录内的图像 - 源路径和目标路径都重复拼接了
.jpg后缀,且目标路径没有保留原文件名,会导致所有匹配的文件互相覆盖,最终仅保留最后一个匹配的文件
- 拼接源文件路径时没有带上
- 冗余判断:已经在遍历文件列表,没有提前过滤非jpg文件,大量无效判断占用算力
优化方案
核心思路是减少重复IO、降低匹配时间复杂度,优化后全程仅需读取1次CSV、遍历1次图像目录,总时间复杂度降到O(200万),处理速度可以提升上千倍。
优化后代码
import shutil import os import csv # 配置参数,替换成你自己的实际路径 ImgFolder = "你的NAS图像根目录路径" DictFolder = "你的ID列表CSV文件路径" dstFolder = "目标存储目录路径" # 第一步:提前一次性读取所有目标ID到集合,集合的查询时间复杂度为O(1) target_ids = set() with open(DictFolder, 'r', encoding='utf-8', newline='') as f: csv_reader = csv.DictReader(f) for row in csv_reader: # 去掉ID前后的空白符避免匹配失败 target_ids.add(row['id_line'].strip()) # 第二步:仅遍历一次所有图像文件 for root, dirs, files in os.walk(ImgFolder): for file in files: # 先过滤非jpg文件,跳过无效文件减少后续判断 if not file.lower().endswith('.jpg'): continue # 正确拼接当前文件的完整绝对路径 src_path = os.path.join(root, file) # 匹配ID:如果你的图像文件名就是「ID.jpg」格式,直接用下面这行代码,匹配更快更准确 # if file.rsplit('.', 1)[0] in target_ids: # 如果ID是文件名的一部分,用下面的判断逻辑 if any(target_id in file for target_id in target_ids): # 目标路径保留原文件名,避免覆盖 dst_path = os.path.join(dstFolder, file) shutil.copyfile(src_path, dst_path)
额外提速技巧
- 先把NAS共享目录映射为Windows本地盘符,减少网络IO的寻址开销
- 如果你的ID是文件名的固定组成部分(比如文件名前缀就是ID),直接提取文件名对应位置和ID集合匹配,不需要用
in遍历判断,匹配速度会进一步提升 - 如果复制操作耗时较长,可以引入多线程处理复制任务,复制是IO密集型操作,多线程可以充分利用网络IO的等待时间,进一步压缩总耗时
内容的提问来源于stack exchange,提问作者CorpA
相关产品推荐
相关产品推荐

