如何高效处理300个大文本文件并计算每行平均值?
优化多文件逐行平均值计算脚本(处理300个30MB文件)
原脚本的核心问题
原脚本一次性将所有文件的全部数据加载到内存中(先转成列表再转numpy数组),这会导致内存占用过高(300个30MB文件的纯数值数据,仅numpy数组就会占用数GB内存),同时文件读取和数据转换的额外开销也拖慢了整体速度。
优化方案:逐行累加+内存友好型实现
核心思路是不加载全部数据到内存,而是同时打开所有文件,逐行读取对应行的数值并累加求和,最后除以文件数得到平均值。这种方式内存占用恒定(仅需存储每行的累加和),IO效率大幅提升。
优化后的代码
import glob from contextlib import ExitStack directory = '/directory/*.txt' files = glob.glob(directory) num_files = len(files) # 先获取文件的行数(所有文件行数相同) with open(files[0], 'r') as f: line_count = sum(1 for _ in f) # 初始化累加数组,内存占用仅与行数相关 sums = [0] * line_count # 使用ExitStack安全管理多个文件句柄 with ExitStack() as stack: file_handles = [stack.enter_context(open(file, 'r')) for file in files] # 逐行遍历,累加所有文件对应行的数值 for idx in range(line_count): for fh in file_handles: val = int(fh.readline().strip()) sums[idx] += val # 计算平均值并取整 averages = [round(total / num_files) for total in sums] # 一次性写入结果,减少IO操作次数 with open('my_new_average_file.txt', 'w') as f: f.write('\n'.join(map(str, averages)) + '\n') print("done")
进一步提速:用mmap映射文件
如果需要更快的文件读取速度,可以用mmap将文件直接映射到内存,减少用户态与内核态的数据拷贝开销:
import glob import mmap from contextlib import ExitStack directory = '/directory/*.txt' files = glob.glob(directory) num_files = len(files) # 获取文件行数 with open(files[0], 'r') as f: line_count = sum(1 for _ in f) sums = [0] * line_count with ExitStack() as stack: mapped_files = [] for file in files: fh = stack.enter_context(open(file, 'r+b')) mm = stack.enter_context(mmap.mmap(fh.fileno(), length=0, access=mmap.ACCESS_READ)) mapped_files.append(mm) # 逐行读取映射文件的内容并累加 for idx in range(line_count): for mm in mapped_files: line = b'' while True: c = mm.read(1) if c == b'\n' or not c: break line += c val = int(line.strip()) sums[idx] += val averages = [round(total / num_files) for total in sums] with open('my_new_average_file.txt', 'w') as f: f.write('\n'.join(map(str, averages)) + '\n') print("done")
优化核心要点
- 内存占用最小化:仅存储每行的累加和,内存消耗与文件数量无关,仅依赖文件行数
- IO效率提升:逐行并行读取避免大文件一次性加载,一次性写入结果减少IO调用次数
- 跳过冗余转换:无需将数据转存为列表或numpy数组,直接进行数值计算,减少中间开销
内容的提问来源于stack exchange,提问作者Sunna
相关产品推荐
相关产品推荐

