如何批量执行Python脚本处理多文件夹CSV文件并生成对应列均值输出文件
解决方案
方案1:仅修改Bash脚本(Python脚本无需改动)
你原有Bash脚本的逻辑存在错误:向Python脚本传递的是单个CSV文件路径,但你的Python脚本实际接收的第一个参数是待处理文件夹路径。修改后的Bash脚本可批量遍历所有目标文件夹:
#!/usr/bin/env bash # 配置项:修改为你存放所有待处理文件夹的根目录 ROOT_DIR="./" # 匹配所有待处理文件夹,示例是匹配名称带escen的文件夹,可根据实际规则修改 find "${ROOT_DIR}" -maxdepth 1 -type d -name "*escen*" | sort | while read -r folder; do # 生成输出文件名,可根据需求修改命名规则 output_name="results_$(basename "${folder}").csv" # 调用Python脚本,路径加引号避免空格问题 python3 generator2.py "${folder}/" "${output_name}" done
说明
-maxdepth 1表示仅遍历根目录下的一级子文件夹,若需要递归查找子文件夹可去掉该参数sort保证文件夹处理顺序和名称排序一致,符合你保留原有顺序的要求- 输出文件名和对应文件夹绑定,不会出现混淆
方案2:全Python实现(推荐,无需依赖Bash,跨平台兼容性好)
直接修改Python脚本,一次性完成多文件夹遍历+处理,不需要额外编写Bash脚本,修改后的完整代码如下:
import os import sys import numpy as np import pandas as pd from csv import DictReader # -------------------------- 配置项 -------------------------- # 存放所有待处理文件夹的根目录 ROOT_DIR = "./" # 待处理文件夹的名称匹配规则,示例为匹配名称含escen的文件夹 FOLDER_PATTERN = "escen" # 输出文件命名前缀 OUTPUT_PREFIX = "results_" # CSV分隔符 DELIMITER = ";" # ----------------------------------------------------------- def process_single_folder(input_folder, output_file): # 统一文件夹路径格式 input_folder = input_folder.rstrip(os.sep) + os.sep # 按规则排序文件夹内的CSV文件 data_in_files = sorted( [f for f in os.listdir(input_folder) if f.endswith('.csv')], key=lambda x: int(x.split('_')[1]) ) nodes = {} for file_name in data_in_files: file_path = os.path.join(input_folder, file_name) with open(file_path, 'r', encoding='utf-8') as f: data = DictReader(f, delimiter=DELIMITER) for line in data: node_code = line['node_code'] if node_code not in nodes: nodes[node_code] = [] nodes[node_code].append([ node_code, line['throughput[Mbps]'], line['data_packets_sent'], line['data_packets_lost'], line['rts_cts_sent'], line['rts_cts_lost'] ]) # 生成输出内容 output = '' max_data_len = max([len(nodes[n]) for n in nodes]) keys = sorted(nodes.keys()) for i in range(max_data_len): if i == 0: header = ';'.join(['node_code;throughput[Mbps];Data packets_sent;Data_packets lost;rts_cts_sent;rts_cts_lost'] * len(keys)) output += header + '\n' for idx, key in enumerate(keys): if idx != 0: output += ';' if i >= len(nodes[key]): output += ';;;;;' continue output += ';'.join(nodes[key][i]) output += '\n' # 写入临时结果 with open(output_file, 'w', encoding='utf-8') as f: f.write(output) # 计算均值 df = pd.read_csv(output_file, sep=DELIMITER) # 兼容新版pandas,替换已废弃的append方法 new_row = pd.DataFrame([{'node_code': "Promedio"}]) df = pd.concat([df, new_row], ignore_index=True) length = len(df) for i in range(len(df.columns)//6): col_name = 'throughput[Mbps]' if i == 0 else f'throughput[Mbps].{i}' df.loc[length-1, col_name] = np.average(df[col_name][:-1]) # 写入最终结果 df.to_csv(output_file, sep=DELIMITER, index=False) print(f"处理完成:{output_file}") if __name__ == "__main__": # 获取所有符合规则的文件夹并排序 target_folders = [] for entry in os.scandir(ROOT_DIR): if entry.is_dir() and FOLDER_PATTERN in entry.name: target_folders.append(entry.path) # 按名称排序保证处理顺序 target_folders.sort() # 批量处理 for folder in target_folders: folder_basename = os.path.basename(folder) output_file = f"{OUTPUT_PREFIX}{folder_basename}.csv" process_single_folder(folder, output_file)
优化点
- 用
os.path.join拼接路径,兼容Windows、Linux系统 - 用
with上下文管理器打开文件,避免文件句柄泄漏 - 替换已废弃的
DataFrame.append方法为pd.concat,兼容新版pandas - 所有可调整参数统一放在头部,修改方便
内容的提问来源于stack exchange,提问作者Edwin Reyes
相关产品推荐
相关产品推荐

