Python处理超大型CSV时如何不加载全量内存实现字典列表排序
解决方案
方案1:哈希累加(优先推荐,适用99%场景)
核心逻辑是直接遍历单行数据,用字典按name累加数值,完全不需要全量排序,内存仅占用去重后的name和对应总和的空间,时间复杂度为O(n),性能远高于原有排序方案。
实现代码
import csv from collections import defaultdict def main(): name_total = defaultdict(int) # 逐行读取,不会全量加载到内存 with open("input.csv", "r", encoding="utf-8") as csvfile: reader = csv.DictReader(csvfile) for row in reader: name_total[row["name"]] += int(row["number"]) # 写入结果文件 with open("output.csv", "w", encoding="utf-8", newline="") as final_csvfile: fieldnames = ["name", "number"] writer = csv.DictWriter(final_csvfile, fieldnames=fieldnames) writer.writeheader() for name, total in name_total.items(): writer.writerow({ "name": name, "number": str(total) }) if __name__ == "__main__": main()
适用场景
只要去重后的name数量没有超过内存承载上限(比如千万级以下的不同name,内存占用仅几百MB),该方案都是最优选择。
方案2:外部排序+归并分组(极端场景适用)
如果遇到去重后的name数量也大到无法装入内存的极端情况,可以采用外排序思路处理:
- 第一步:将大CSV拆分为多个大小适合内存的小文件,每个小文件单独按name排序后写入临时存储
- 第二步:对多个已排序的临时文件做流式归并,归并过程中直接按name分组求和,不需要加载全量数据
- 简化实现:Linux/macOS环境可以直接调用系统自带的
sort命令,原生支持外排序,性能远高于自定义实现,配合awk一行命令即可完成需求:
# 按第一列name排序,跳过表头后分组求和,直接输出结果 sort -t',' -k1,1 input.csv | awk -F',' 'NR==1{next} {a[$1]+=$2} END{print "name,number";for(i in a) print i","a[i]}' > output.csv
原有代码问题说明
原有sorted+itertools.groupby的实现思路仅适合小数据集,sorted方法会强制把生成器转为全量列表加载到内存,5000万行数据通常会占用数GB到数十GB内存,自然会触发系统OOM终止进程。
内容的提问来源于stack exchange,提问作者Caspian
相关产品推荐
相关产品推荐

