Python用ijson+多进程解析12GB大JSON文件出现内存错误求解决方案
内存错误原因排查及解决方案
核心问题1:多进程逻辑错误+全局变量内存爆炸
- 多进程模式下每个子进程会独立复制一份主进程的
mydata变量,500万条论文对应千万级作者关联记录,每个子进程都在本地攒大体积DataFrame,内存会直接翻倍撑爆。且多进程全局变量不共享,主进程最后拿到的mydata还是初始空对象,本身逻辑就不成立。 - Pandas的
append方法是低效操作,每次调用都会生成全新的DataFrame对象,旧对象不会立即释放,内存占用会持续攀升。
修复方案
- 放弃用全局DataFrame攒中间数据,改为子进程直接把作者统计数据写入临时CSV/数据库临时表,所有任务跑完后再统一读取聚合。
- 就算要攒中间数据,也用Python原生列表存字典,最后一次性转DataFrame,比反复append效率高10倍以上。
核心问题2:进程池任务队列溢出,ijson流式特性完全失效
- 你直接循环500万次调用
p.apply_async(parse,(paper,)),所有解析出来的paper对象会全部塞进进程池的待执行队列,相当于把整个12G JSON转成Python对象全部加载到内存,完全浪费了ijson的流式解析能力。
修复方案
- 改用
imap/imap_unordered限制并发任务数,或者设置队列长度阈值,每攒够1000条任务就等一批执行完再塞新的,避免队列爆内存。 - 给进程池加
maxtasksperchild参数,每个子进程处理完固定数量任务就重启,释放内存碎片。
核心问题3:无效操作带来的额外内存开销
- 子进程中
paper_authors本身已经是解析完成的Python列表,你额外做json.dumps再用ijson解析完全是多余操作,既浪费CPU又额外占用内存存序列化后的字符串。
修复方案
直接遍历paper_authors即可,删掉冗余代码:
# 删掉以下三行 # paper_authors_json = json.dumps(paper_authors) # obj = ijson.items(paper_authors_json,'item') # for author in obj: # 替换为 for author in paper_authors:
核心问题4:数据库操作带来的内存开销
- 单条ORM save操作会触发框架的对象缓存,运行时间久了缓存会攒大量对象占用内存。
- 最后主进程用
iterrows遍历大df单条插入,也会有大量内存开销。
修复方案
- 数据库操作改用
bulk_create批量插入,每攒1000条数据提交一次,每次批量插入后清理ORM缓存。 - 最后聚合后的ratings数据也用
bulk_create批量插入,不要用iterrows单条循环。
额外优化建议
- 可以先把聚合逻辑放到子进程做,每个子进程处理一批论文就先做一次局部聚合,再把聚合后的结果返回主进程做全局聚合,进一步减少数据传输和内存占用。
- 进程数根据机器CPU核数+内存大小调整,内存偏小的话可以先开2进程测试跑通再逐步上调。
内容的提问来源于stack exchange,提问作者Δημήτριος Ιντζελερ
相关产品推荐
相关产品推荐

