You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python顺序处理多文件时内存溢出问题及解决方案咨询

解决大数据合并时的内存溢出问题

我完全懂你现在的痛点——明明已经把大文件拆成了小份,处理第一个文件还好好的,到第二个就内存爆了,用了del和gc.collect()也没见效,直接卡得Jupyter动不了。下面给你几个针对性的解决方案,你可以从易到难逐一尝试:

1. 先搞定最浪费内存的重复加载问题

你现在每次调用merge_data都会重新读一遍db1.csv和db2.csv,这完全是没必要的重复操作!这两个文件是静态的,只需要加载一次就行,重复读取会平白占用大量内存,这应该是导致你内存撑爆的核心原因之一。

修改代码如下:

# 把静态数据移到函数外面,只加载一次
db1 = pd.read_csv('../data/db1.csv')
db2 = pd.read_csv('../data/db2.csv')

def merge_data(path):
    temp = pd.read_csv(path)
    temp = pd.merge(temp, db1, on='db1_id', how='left')
    temp = pd.merge(temp, db2, on='db2_id', how='left')
    return temp.drop('target', axis=1), temp['target']

这个改动最小,但效果绝对立竿见影。

2. 给内存释放加上“强制保险”

有时候del变量后,Python的垃圾回收不会立刻生效,尤其是Jupyter环境会悄悄保留变量的历史引用,导致内存没真正释放。你可以在循环里试试这套组合拳:

import gc

for f in files_list:
    Xdf, ydf = merge_data(f)
    # 这里写你的Xdf、ydf处理逻辑
    
    # 处理完立刻清理,别等
    del Xdf, ydf
    # 强制触发垃圾回收,并且等待回收完成
    gc.collect()
    # 针对Jupyter的专属操作:清除变量的历史引用
    %reset_selective -f Xdf ydf

%reset_selective是Jupyter的魔法命令,能直接干掉指定变量的所有引用,避免Jupyter偷偷占着内存不放。

3. 给数据“瘦身”:优化读取和存储类型

合并后每条记录有3000列,很多列可能根本不需要,或者可以用更紧凑的类型存储:

  • 读取时只拿需要的列:如果子文件里只有db1_id、db2_id和target是必须的,其他列直接跳过:
    temp = pd.read_csv(path, usecols=['db1_id', 'db2_id', 'target'])
    
  • 压缩静态数据的类型:检查db1和db2的列,把字符串列转成category类型(如果重复值多),把整数列转成更小的数值类型(比如int64转int32,只要数值范围够):
    # 把重复多的字符串列转成category
    db1['category_col'] = db1['category_col'].astype('category')
    # 自动把整数列压缩到最小合适类型
    db1['int_col'] = pd.to_numeric(db1['int_col'], downcast='integer')
    

这一步能大幅降低静态数据的内存占用。

4. 给单个子文件再分块

如果10万条记录合并后还是占内存,那就把单个子文件再拆成更小的块处理:

def merge_data(path):
    # 每次读1万条,可根据内存情况调整chunksize
    chunks = pd.read_csv(path, chunksize=10000)
    X_list = []
    y_list = []
    for chunk in chunks:
        chunk = pd.merge(chunk, db1, on='db1_id', how='left')
        chunk = pd.merge(chunk, db2, on='db2_id', how='left')
        X_list.append(chunk.drop('target', axis=1))
        y_list.append(chunk['target'])
    # 合并所有小块
    Xdf = pd.concat(X_list, ignore_index=True)
    ydf = pd.concat(y_list, ignore_index=True)
    return Xdf, ydf

这样每次只处理1万条数据的合并,内存压力会小很多。

5. 换用更适合大数据的工具

如果Pandas实在顶不住,可以试试专门处理超大数据的库:

  • Dask:用法和Pandas几乎一致,会自动分块处理超出内存的数据,支持并行计算。
  • Vaex:用内存映射技术读取数据,不需要把整个数据集加载到内存,适合处理亿级别的数据。

比如用Dask的示例代码:

import dask.dataframe as dd

# 用Dask读取静态数据
db1 = dd.read_csv('../data/db1.csv')
db2 = dd.read_csv('../data/db2.csv')

for f in files_list:
    temp = dd.read_csv(f)
    temp = temp.merge(db1, on='db1_id', how='left')
    temp = temp.merge(db2, on='db2_id', how='left')
    Xdf = temp.drop('target', axis=1)
    ydf = temp['target']
    # 直接写入文件,不要把数据留在内存里
    Xdf.to_csv(f'processed_X_{f}.csv', single_file=True)
    ydf.to_csv(f'processed_y_{f}.csv', single_file=True)

建议你先从第1、2点开始尝试,这两个改动最小,见效最快。

内容的提问来源于stack exchange,提问作者Hossein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:36:23