VSCode交互查看器中matplotlib绘图无法跨单元格调用显示问题
问题原因
VSCode里用#%%分隔的交互单元格本质是Jupyter风格的代码块,默认配置下,单元格内执行完plt.show()之后,matplotlib会自动清空全局绘图状态,把已经渲染完成的figure对象从pyplot的内部注册表中移除,回收对应的内存资源。
你第一次运行绘图单元格时,plt.show()触发渲染、正常显示出带标注的散点图(效果如下图),渲染完成后这个画布对象就已经被销毁了,pyplot的状态栈里没有任何待显示的绘图内容。
这时候你在新单元格单独跑plt.show(),没有可渲染的画布自然什么都出不来;单独写一行plt只是引用了pyplot模块本身,根本不会触发任何渲染逻辑,当然也不会显示图。
很多人会误以为matplotlib会一直留存之前画过的图,实际上这种自动清理是交互环境的默认行为,目的是避免大量无用的旧绘图对象堆积占用内存。
跨单元格调用已生成绘图的方法
核心原则是不要依赖pyplot的全局状态存图,手动持有figure对象的引用,具体操作如下:
- 第一步:在创建绘图的单元格里,把
plt.subplots()返回的fig对象保留下来,不要在这个单元格里调用plt.show()触发自动清理。示例代码:
#%% 单元格1:创建并持有绘图对象 import matplotlib.pyplot as plt y = [3.2, 3.9, 3.7, 3.5, 3.02199] x = [0.15, 0.3, 0.45, 0.6, 0.75] n = [155, "outliner", 293, 230, 670] # 用变量接住返回的fig对象,这是后续跨单元格调用的关键 fig, ax = plt.subplots() ax.scatter(x, y) plt.xlabel('the x axis') plt.ylabel('the y axis') for i, txt in enumerate(n): ax.annotate(txt, (x[i], y[i])) # 不要在这里调用plt.show(),避免触发自动清理
- 第二步:在后续任意需要显示绘图的单元格里,直接引用持有的
fig对象即可渲染显示,兼容性更好的写法是调用IPython的display方法:
#%% 任意后续单元格:显示已生成的绘图 from IPython.display import display display(fig) # 交互环境下直接写fig也能触发渲染 # fig
如果需要对图做二次修改(比如加标注、改坐标轴),直接在新单元格里操作ax对象之后,再调用display(fig)就能显示修改后的效果。
注意:不要尝试用
plt.gcf()跨单元格获取之前的画布,只要之前触发过自动清理,plt.gcf()只会返回一个全新的空白画布,拿不到你之前绘制的内容。
内容的提问来源于stack exchange,提问作者darren
相关产品推荐
相关产品推荐

