如何用Python读取超100万行的Excel/CSV并拆分文件?
超百万行Excel/CSV文件拆分方案
原代码存在的问题
- 一次性加载全量数据到内存,超百万行极易触发内存溢出
- 拆分逻辑错误:
i*n_partitions的计算方式完全错误,会导致拆分的行范围混乱 - 未考虑Excel单表最大行数限制(Excel 2007+ 单表最多支持 1048576行),若拆分后的文件行数超过这个值,写入Excel时会报错
优化方案:分块读取+合规拆分
核心思路是分块读取源文件,避免一次性加载全量数据,同时确保每个输出文件的行数不超过Excel单表上限。
1. CSV文件拆分(效率最高)
CSV文件支持流式分块读取,内存占用极低:
import pandas as pd # 配置参数 source_path = "/path/to/source.csv" output_dir = "/output/path/" # 每个拆分文件的最大行数,不超过Excel单表上限 max_rows_per_file = 900000 # 或直接设为1048576 header_written = False file_index = 0 # 分块读取CSV for chunk in pd.read_csv(source_path, chunksize=max_rows_per_file): # 写入文件 output_path = f"{output_dir}/split_{file_index}.csv" chunk.to_csv(output_path, index=False, header=not header_written) # 第一次写入后,后续文件不再写表头 if not header_written: header_written = True file_index += 1 print(f"拆分完成,共生成 {file_index} 个文件")
2. Excel文件拆分(适配超大数据量)
使用pandas.read_excel的chunksize参数分块读取,注意指定支持xlsx格式的引擎openpyxl:
import pandas as pd # 配置参数 source_path = "/path/to/source.xlsx" output_dir = "/output/path/" max_rows_per_file = 900000 # 不超过1048576 header_written = False file_index = 0 # 分块读取Excel(需先安装openpyxl:pip install openpyxl) for chunk in pd.read_excel(source_path, engine="openpyxl", chunksize=max_rows_per_file): output_path = f"{output_dir}/split_{file_index}.xlsx" # 写入Excel,保留表头 chunk.to_excel(output_path, sheet_name="data", index=False, header=not header_written) if not header_written: header_written = True file_index += 1 print(f"拆分完成,共生成 {file_index} 个文件")
3. 自定义拆分数量(如固定拆成3个文件)
如果需要固定拆分数量(比如270万行拆成3个90万行文件),可以先计算总行数,再确定每个文件的行数:
import pandas as pd source_path = "/path/to/source.xlsx" output_dir = "/output/path/" n_partitions = 3 # 先获取总行数(仅读取表头和行数,不加载全量数据) with pd.ExcelFile(source_path, engine="openpyxl") as xls: df_total = pd.read_excel(xls, nrows=0) total_rows = xls.parse(xls.sheet_names[0]).shape[0] # 计算每个文件的行数 chunk_size = total_rows // n_partitions # 处理余数,确保最后一个文件包含剩余行 remainder = total_rows % n_partitions header_written = False current_row = 0 for i in range(n_partitions): # 当前文件的行数:前n_partitions-1个文件用chunk_size,最后一个加上余数 current_chunk_size = chunk_size + (1 if i == n_partitions -1 else 0) if remainder else chunk_size # 分块读取指定范围的行 chunk = pd.read_excel(source_path, engine="openpyxl", skiprows=current_row+1, nrows=current_chunk_size, header=None) # 手动设置表头 chunk.columns = df_total.columns # 写入文件 output_path = f"{output_dir}/test-{i}.xlsx" chunk.to_excel(output_path, sheet_name="a", index=False) current_row += current_chunk_size print(f"按指定数量拆分完成,共生成 {n_partitions} 个文件")
注意事项
- 若处理Excel文件,需安装
openpyxl引擎:pip install openpyxl - 拆分CSV时可指定编码(如
encoding="utf-8")避免乱码 - 若内存仍紧张,可进一步减小
chunksize的值 - 确保输出目录存在,否则会报错(可提前用
os.makedirs(output_dir, exist_ok=True)创建)
内容的提问来源于stack exchange,提问作者Keshav
相关产品推荐
相关产品推荐

