Python处理2-10GB大CSV文件内存占用过高,如何优化?
处理大型CSV文件的内存优化方案
问题背景
处理2GB至10GB的大型CSV文件时,使用pandas加载全量数据导致内存占用过高,脚本崩溃。即使尝试分块处理仍出现内存不足错误,需解决以下核心问题:
- 不加载全量数据的高效过滤与转换
- 内存友好的结果写入方式
- pandas处理大数据集的最佳实践及替代方案
一、Pandas内存优化最佳实践
1. 精准配置分块与增量写入
不要依赖默认分块参数,结合内存容量调整chunksize,并采用增量写入避免内存堆积:
import pandas as pd def process_csv_chunked(input_file, output_file, some_value, value_mapping): # 先读取表头,避免重复写入 header = pd.read_csv(input_file, nrows=0).columns with open(output_file, 'w') as f: f.write(','.join(header) + '\n') # 根据内存设置合适的分块大小,比如1万行/块 chunk_size = 10000 for chunk in pd.read_csv(input_file, chunksize=chunk_size): # 过滤行 filtered_chunk = chunk[chunk['column_name'] > some_value] # 值映射 filtered_chunk['target_col'] = filtered_chunk['target_col'].map(value_mapping) # 增量写入,关闭表头避免重复 filtered_chunk.to_csv(output_file, mode='a', header=False, index=False)
如果需要跨块聚合(如分组统计),可先用字典缓存分组中间结果,最后统一合并写入。
2. 指定数据类型压缩内存
读取时明确列的dtype,避免pandas自动推断占用冗余内存:
# 按需定义最小合适的数据类型 dtype_spec = { 'id_col': 'int32', 'category_col': 'category', 'float_col': 'float32', 'string_col': 'string[pyarrow]' # pyarrow字符串比原生更省内存 } for chunk in pd.read_csv(input_file, chunksize=10000, dtype=dtype_spec): # 处理逻辑
重复值多的字符串列用category类型,数值列用最小精度类型(如int32替代int64),可降低60%以上内存占用。
3. 按需加载列
只读取需要处理的列,跳过无关数据:
# 仅加载业务需要的列 usecols = ['column_name', 'target_col', 'group_col'] for chunk in pd.read_csv(input_file, chunksize=10000, usecols=usecols, dtype=dtype_spec): # 处理逻辑
二、替代库与技术
1. Dask(兼容Pandas的并行分块工具)
Dask自动处理超内存数据集,API与pandas高度兼容,支持并行计算:
import dask.dataframe as dd def process_with_dask(input_file, output_file, some_value, value_mapping): df = dd.read_csv(input_file, dtype=dtype_spec) # 过滤与映射 filtered_df = df[df['column_name'] > some_value] filtered_df['target_col'] = filtered_df['target_col'].map(value_mapping) # 跨块聚合直接用Dask原生方法 aggregated_df = filtered_df.groupby('group_col').sum() # 输出为单个CSV文件 aggregated_df.to_csv(output_file, single_file=True)
2. 原生CSV模块(极简内存占用)
如果逻辑简单,用Python原生csv模块逐行处理,内存占用趋近于0:
import csv def process_with_csv(input_file, output_file, some_value, value_mapping): with open(input_file, 'r') as infile, open(output_file, 'w', newline='') as outfile: reader = csv.DictReader(infile) writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames) writer.writeheader() for row in reader: # 过滤条件 if float(row['column_name']) > some_value: # 值映射 row['target_col'] = value_mapping.get(row['target_col'], row['target_col']) writer.writerow(row)
缺点是复杂聚合需要自行实现缓存逻辑,适合简单的过滤、映射场景。
3. Vaex(延迟计算型工具)
Vaex采用延迟计算,不加载全量数据到内存,适合快速过滤与统计:
import vaex df = vaex.read_csv(input_file) filtered_df = df[df.column_name > some_value] filtered_df['target_col'] = filtered_df.target_col.map(value_mapping) filtered_df.export_csv(output_file)
三、内存高效写入的最佳实践
- 增量写入优先:分块处理时先写入表头,后续每次追加块数据,避免重复打开文件。
- 避免中间缓存:处理完一个块立即写入,不要将所有块结果存放在内存中统一输出。
- 关闭冗余参数:用pandas写入时,务必设置
header=False(增量阶段)和index=False,减少冗余输出。 - 可选压缩输出:写入
.csv.gz格式,pandas、Dask均支持,既节省磁盘空间也降低IO次数。
内容的提问来源于stack exchange,提问作者Shahnoor
相关产品推荐
相关产品推荐

