10000个ROOT文件分块软链接异常及批量操作提速求助
问题1:SeventhList元素数量不符的原因及解决方法
原因分析
- 整数除法导致分块基数偏差:Python2中
len(AllFileList)/7为整数除法,10000/7=1428(而非精确值1428.571),前6块每块1428个元素,累计8568个,剩余1432个元素应归为第7块。 - 分块逻辑错误:原代码生成
SeventhList的列表推导式会生成大量重叠小切片,而你仅取SeventhList[0](从6*1428=8568开始取1428个元素,到9996为止),漏掉了最后4个元素(9996-10000),导致SeventhList[0]仅1428个元素。
解决方法
替换错误分块逻辑,采用均匀分块方案:
import os StartDir = "/data05/padme/beth/MC_Run660/RawMCFiles" end_dirs = [ "/data05/padme/beth/MC_Run660_FirstSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SecondSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_ThirdSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_FourthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_FifthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SixthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SeventhSeventh/RawMCFiles" ] # 启用排序,确保文件按编号顺序处理 AllFileList = sorted(os.listdir(StartDir), key=lambda x: int(x.split("_")[-1].split(".")[0])) total_files = len(AllFileList) base_size = total_files // 7 remainder = total_files % 7 # 分块:前remainder块各base_size+1个元素,剩余块各base_size个 file_blocks = [] start_idx = 0 for i in range(7): block_size = base_size + 1 if i < remainder else base_size file_blocks.append(AllFileList[start_idx:start_idx+block_size]) start_idx += block_size # 验证各块长度 for idx, block in enumerate(file_blocks, 1): print(f"第{idx}块元素数量: {len(block)}") # 创建软链接(先确保目标目录存在) for block, target_dir in zip(file_blocks, end_dirs): if not os.path.exists(target_dir): os.makedirs(target_dir) for filename in block: src_path = os.path.join(StartDir, filename) dst_path = os.path.join(target_dir, filename) if not os.path.exists(dst_path): os.symlink(src_path, dst_path)
- 核心改进:用整数除法和取余自动分配剩余元素,确保第7块包含1432个元素;启用文件排序避免顺序混乱;简化代码结构,增加目录存在检查和重复链接判断。
问题2:软链接创建速度优化
速度慢的可能原因
- 原代码中每次创建链接都打印文件名,IO打印操作拖慢整体速度;
- 单线程串行处理,未利用并行IO能力;
- 文件系统性能瓶颈(如机械硬盘的元数据操作延迟)。
优化方案
- 移除冗余打印:直接删除
print ii语句,减少不必要的IO开销。 - 多线程并行创建:IO密集型任务适合用多线程加速,示例代码:
import os from concurrent.futures import ThreadPoolExecutor StartDir = "/data05/padme/beth/MC_Run660/RawMCFiles" end_dirs = [ "/data05/padme/beth/MC_Run660_FirstSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SecondSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_ThirdSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_FourthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_FifthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SixthSeventh/RawMCFiles", "/data05/padme/beth/MC_Run660_SeventhSeventh/RawMCFiles" ] AllFileList = sorted(os.listdir(StartDir), key=lambda x: int(x.split("_")[-1].split(".")[0])) total_files = len(AllFileList) base_size = total_files //7 remainder = total_files %7 file_blocks = [] start_idx=0 for i in range(7): block_size = base_size+1 if i < remainder else base_size file_blocks.append(AllFileList[start_idx:start_idx+block_size]) start_idx += block_size # 提前创建所有目标目录 for dir_path in end_dirs: if not os.path.exists(dir_path): os.makedirs(dir_path) # 定义创建链接的函数 def create_symlink(task_args): src, dst = task_args if not os.path.exists(dst): os.symlink(src, dst) # 生成所有任务 tasks = [] for block, target_dir in zip(file_blocks, end_dirs): for filename in block: src_path = os.path.join(StartDir, filename) dst_path = os.path.join(target_dir, filename) tasks.append((src_path, dst_path)) # 多线程执行,线程数可根据系统调整 with ThreadPoolExecutor(max_workers=10) as executor: executor.map(create_symlink, tasks)
- 硬件层面:如果使用机械硬盘,速度提升空间有限;若为SSD,并行操作会有明显提速。此外,避免在单个目录下存储过多文件(你的场景已按块分到不同目录,无需额外处理)。
内容的提问来源于stack exchange,提问作者Beth Long
相关产品推荐
相关产品推荐

