当前位置:首页>python>Python实验跑到一半内存炸了?3个命令定位泄漏点,救回跑了一周的数据

Python实验跑到一半内存炸了?3个命令定位泄漏点,救回跑了一周的数据

  • 2026-09-10 19:23:36
Python实验跑到一半内存炸了?3个命令定位泄漏点,救回跑了一周的数据

去年有回跑一个图像分类实验,模型训练到第80个epoch,宿舍断电前一切正常。第二天重启脚本,内存从8GB慢慢爬到32GB,最后直接被系统kill。一周的数据预处理全白做。

这种场景做科研的人都不陌生:读大CSV、批量处理图片、循环生成中间结果,内存越跑越高。重启能好一会儿,但治标不治本。问题往往不是Python本身,而是代码里某个地方在偷偷吃内存。

今天分享我排查内存问题的3个工具,从"确认元凶"到"定位代码行"再到"找到具体对象",全程不用花钱。

先用htop确认:是不是Python在吃内存

很多科研人第一步就错了——看到电脑卡,直接怀疑Python,然后开始乱改代码。其实先要用系统工具确认:到底是哪个进程在消耗内存。

工具:htop(Linux/macOS)或Windows任务管理器。

打开终端输入htop,按M键按内存排序。如果你的Python进程内存曲线持续上升,说明问题在代码里。如果是其他进程(比如浏览器开了50个标签),那跟Python没关系。

关键观察点:

  • RES
    列:进程实际占用的物理内存,这个数如果一直涨,就是真泄漏。
  • 曲线是否稳定:
    训练模型时内存有波动正常,但完成一个epoch后应该回落或稳定。如果每个epoch都比上一个高,说明有累积。

这一步只用10秒钟,但能避免你后面白忙一场。

再用memory_profiler:定位到具体代码行

确认是Python的问题后,下一步是找到哪一行代码在吃内存。这时候用memory_profiler。

安装:

pip install memory_profiler

用法:在要分析的函数前加@profile装饰器,然后运行:

python -m memory_profiler your_script.py

输出类似这样:

Line #    Mem usage    Increment  Line Contents ===============================================     12     85.2 MiB     85.2 MiB  @profile     13                             def process_data():     14    105.4 MiB     20.2 MiB      df = pd.read_csv("data.csv")     15    305.4 MiB    200.0 MiB      features = df.apply(complex_transform, axis=1)     16    505.4 MiB    200.0 MiB      result = features.tolist()

每一行的增量(Increment)清清楚楚。上面的例子中,真正的问题是features.tolist()和df.apply()各涨了200MB。如果你原本怀疑是read_csv,这里就能看出不是它。

科研场景里最常见的内存大户:

  • pd.read_csv()
    读整个大文件;
  • .tolist()
    把numpy数组转成Python列表;
  • 循环里不断append大对象,却没有及时清理;
  • matplotlib画图时累积figure对象,没调用plt.close()。

最后用tracemalloc:找到泄漏的具体对象

有些问题更隐蔽:内存不是在某一行突然爆涨,而是慢慢累积。比如循环里不断创建缓存、回调函数持有引用、全局列表无限增长。这时候要用Python内置的tracemalloc。

它是Python标准库,不用安装。

import tracemalloc  tracemalloc.start()  # 运行你的代码 for epoch in range(10):     train_one_epoch()          # 每个epoch后快照对比     snapshot = tracemalloc.take_snapshot()     top_stats = snapshot.statistics('lineno')[:5]          print(f" === Epoch {epoch} 内存增长TOP5 ===")     for stat in top_stats:         print(stat)

输出会告诉你:哪个文件、哪一行、分配了多少内存、增长了多少。比如:

<frozen importlib._bootstrap>:228: size=4855 KiB (+4855 KiB), count=39332 (+39332) my_script.py:42: size=2048 KiB (+1024 KiB), count=256 (+128)

第二行显示my_script.py第42行,这个epoch比上一个多了1024KB。连续几个epoch都涨,基本就是泄漏点。

3个最容易踩的坑

  • 坑1:循环里累积结果。results = []
    然后每个epoch都results.append(big_array),最后内存自然爆炸。解决:只保留必要指标,大数据写到磁盘。
  • 坑2:DataFrame的隐形拷贝。df[df.label == 1]
    会返回新DataFrame,如果循环里反复做,内存翻倍。解决:用inplace=True或先取索引再批量操作。
  • 坑3:没关的figure。
    matplotlib每画一张图就创建一个figure对象,循环里不plt.close(),内存会被吃光。解决:画图后立刻关闭,或用plt.clf()。

免费还是付费?

这3个工具全是免费的:

  • htop
    :开源免费;
  • memory_profiler
    :MIT协议,pip直接装;
  • tracemalloc
    :Python 3.4+内置,零成本。

不需要买任何商业性能分析工具,科研场景完全够用。

关注后回复【内存排查】,领取:

  • 内存排查3件套完整命令速查表
  • 科研代码常见内存泄漏自查清单(10项)
  • tracemalloc对比快照模板代码

你遇到过最离谱的内存爆炸场景是什么?是CSV太大、循环没清缓存,还是画图没关figure?评论区说说,点赞最高的我整理成一期"内存陷阱大全"。

这是「科研人效率工具系列」第14期,上期:论文Introduction写到凌晨3点?这个4段式模板让我2小时写完开头。下期预告:AI辅助文献综述:30篇论文1小时理清研究领域脉络。

— 关注「科研创新社」,每天一个科研效率提升技巧 —

最新文章

随机文章