使用Python的ijson转换250GB+超大JSON为CSV遇崩溃问题求助
250GB超大JSON转CSV的内存友好解决方案
需要将一个250GB的超大JSON文件转换为CSV,该JSON包含BuildingSiteList、BuildingSiteOwnershipList、BuildingsList等多个分支,仅需提取BuildingsList下的数据。原基于ijson的代码在小测试文件(60KB)上运行正常,但处理大文件时直接导致电脑崩溃——核心原因是ijson.items(input_file, "BuildingsList")会将整个BuildingsList数组一次性加载到内存,完全无法适配250GB级别的文件。
核心优化点
原代码的致命问题是一次性加载整个目标数组,正确的做法是逐个迭代BuildingsList中的单个对象,通过修改ijson的路径表达式实现内存零压力的流式处理:
- 将ijson的路径从
"BuildingsList"改为"BuildingsList.item",每次仅读取并处理一个建筑对象,内存占用始终保持在极低水平 - 简化循环逻辑,避免不必要的嵌套遍历
- 合理调整缓冲区大小,平衡内存占用与磁盘IO效率
优化后的完整代码
import ijson import csv input_file_path = 'path to json file' output_file_path = 'path to csv file' # 指定需要导出的CSV字段,注意:字段名需与JSON中的键完全匹配(JSON大小写敏感) desired_fieldnames = ["ID", "LocalityCode", "Coordinates", "BuildingType", "RentalStatus"] # 缓冲区大小:根据自身内存情况调整,建议10000-50000之间 buffer_size = 30000 rows_buffer = [] def write_buffer(writer, buffer): writer.writerows(buffer) # 用writerows替代循环,提升写入效率 with open(input_file_path, 'rb') as input_file, open(output_file_path, 'w', newline='', encoding='utf-8') as output_file: # 关键:逐个读取BuildingsList下的单个对象,而非整个数组 building_objects = ijson.items(input_file, "BuildingsList.item") writer = csv.DictWriter(output_file, fieldnames=desired_fieldnames) writer.writeheader() for item in building_objects: # 过滤出需要的字段,缺失字段填充空字符串 filtered_item = {field: item.get(field, '') for field in desired_fieldnames} rows_buffer.append(filtered_item) # 缓冲区满时批量写入 if len(rows_buffer) >= buffer_size: write_buffer(writer, rows_buffer) rows_buffer = [] # 写入剩余的缓冲数据 if rows_buffer: write_buffer(writer, rows_buffer)
额外注意事项
- 确保JSON文件格式合法,无语法错误,否则ijson会在流式处理中抛出异常
- 若磁盘写入速度较慢,可适当增大缓冲区大小,但不要超过可用内存的10%
- 避免在循环中添加复杂计算或IO操作,保持数据处理逻辑轻量化
内容的提问来源于stack exchange,提问作者user24506501
相关产品推荐
相关产品推荐

