plt.close()没起作用是因为只关闭当前figure而非指定对象,且matplotlib缓存所有figure;应改用plt.close(fig)或plt.close('all'),配合非交互后端、上下文管理器及弱引用避免内存泄漏。

plt.close() 为什么没起作用?
调用 plt.close() 却发现内存持续上涨,通常是因为你只关了当前 figure,而没关指定对象。Matplotlib 默认维护一个 figure 管理器(matplotlib.pyplot._pylab_helpers.Gcf),所有通过 plt.plot()、plt.figure() 创建的 figure 都会被缓存,不显式清理就会一直占内存。
实操建议:
- 避免无参数调用
plt.close(),改用plt.close(fig)或plt.close('all') - 如果用面向对象方式创建,务必保存
fig对象并显式关闭:fig, ax = plt.subplots()<br># ... 绘图逻辑<br>plt.close(fig) # 不是 plt.close()
- 确认没有残留的
plt.show()—— 它会阻塞并隐式 hold figure,尤其在非交互环境(如服务器脚本)中极易引发泄漏
Figure 对象未被垃圾回收的常见原因
即使调用了 plt.close(fig),Python 的 GC 也可能因强引用未断而无法释放 figure。最典型的是:把 ax 或 fig 存进全局列表、类属性、闭包,或意外绑定到事件回调(比如 fig.canvas.mpl_connect)。
实操建议:
- 检查是否有类似
self.figs.append(fig)的代码,改成只存必要数据(如图像二进制或文件路径),而非 figure 对象本身 - 使用
weakref管理回调引用:import weakref<br>def on_click(event):<br> if fig_ref() is not None:<br> # 处理逻辑<br>fig_ref = weakref.ref(fig)
- 用
sys.getrefcount(fig)快速验证引用数是否异常高(注意:该函数自身会+1,需比对差值)
批量绘图时推荐的上下文管理写法
靠人工记着调 close 容易遗漏,尤其在循环或异常路径中。用上下文管理器能强制释放,且语义清晰。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
实操建议:
- 封装一个轻量 context manager:
from contextlib import contextmanager
@contextmanager
def managed_fig(*args, **kwargs):
fig = plt.figure(*args, **kwargs)
try:
yield fig
finally:
plt.close(fig)
然后这样用:
for i in range(1000):
with managed_fig() as fig:
ax = fig.add_subplot(111)
ax.plot(data[i])
fig.savefig(f"plot_{i}.png")
- 不要在 context 内调用
plt.show()或依赖全局状态(如plt.style.use()应放在外层统一设置) - 如果必须复用 figure(如动画),改用
fig.clear()+ax.clear(),比反复新建更省内存
后端选择对内存行为的影响
默认后端(如 TkAgg 或 Qt5Agg)会在后台维持 GUI 资源,即使没显示窗口。批量生成图表时,这些资源不会随 plt.close() 自动释放。
实操建议:
- 服务端脚本务必切换为非交互后端:
import matplotlib<br>matplotlib.use('Agg') # 必须在 import pyplot 之前 - 确认生效:
print(matplotlib.get_backend())应输出Agg,而非Qt5Agg等 - 某些旧版 Matplotlib(Agg 下仍可能泄漏字体缓存,可加一行:
plt.rcParams['font.family'] = 'DejaVu Sans'避免动态加载字体
真正麻烦的不是 close 没写,而是 figure 被谁悄悄 hold 住了——查引用链比猜错误更有效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










