PyCharm 2017.3.3社区版中Matplotlib仅断点调试时正常显示多图问题
解决Matplotlib循环绘图时仅显示首图且卡顿的问题
嘿,我刚好碰到过类似的问题!你在PyCharm 2017.3.3社区版里遇到的这个情况,本质是Matplotlib默认的阻塞式绘图机制在搞鬼——直接运行或无断点调试时,第一个plt.show()会卡住整个程序的执行,后面的循环代码根本没机会运行;而断点逐步调试时,你关闭当前窗口后程序才会继续执行下一次循环,所以所有图表都能正常显示。之前用更少图表运行没问题,是因为阻塞时间短没被你注意到,图表数量增多后这个问题就凸显出来了。
问题根源
Matplotlib默认使用的后端(比如TkAgg)在调用plt.show()时,会进入阻塞状态,直到你手动关闭当前绘图窗口才会继续执行后续代码。所以当你在循环里直接调用plt.show(),程序就会卡在第一个窗口,无法推进到下一次迭代。
可行解决方案
方案1:每次绘图后关闭窗口(最简单直接)
在每次循环的plt.show()之后,调用plt.close()关闭当前绘图窗口,让程序能继续执行下一次循环:
plt.show() plt.close() # 关闭当前窗口,释放资源,让程序继续往下走
方案2:启用交互式模式
在代码开头启用Matplotlib的交互式模式,这样plt.show()不会阻塞程序,所有图表会依次弹出,最后可以用plt.ioff()和plt.show()保持窗口不自动关闭:
import matplotlib.pyplot as plt plt.ion() # 启用交互式模式 # 你的循环绘图代码... plt.ioff() # 关闭交互式模式 plt.show() # 保持所有窗口打开
方案3:使用面向对象式绘图(更优雅,推荐长期使用)
避开pyplot的全局状态,改用图和子图对象来管理绘图,能更精准控制每个窗口的生命周期:
# 替换循环内的绘图代码: fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8)) # 创建图和子图对象 if not histData[0].empty or not histData[1].empty or not histData[2].empty: n, bins, patches = ax1.hist(histData, np.arange(0.5,13, 1), stacked=True, label=types, color=col, rwidth=0.8) ax1.legend() ax1.set_xticks(range(1,13)) ax1.set_xticklabels(("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")) ax1.set_title(f"Clase {comp+1} de {nclasses}") ax2.stem(mclass) ax2.set_xticks(range(14)) ax2.set_xticklabels(list(df.loc[:, "M":"Salida2_4"])) ax2.set_title("Medias de características para la clase") plt.show() plt.close(fig) # 关闭当前图对象
修正后的完整代码(用方案1快速解决)
这里给出直接修改后的代码,只加了一行plt.close(),适合你的场景:
import matplotlib.pyplot as plt import pandas as pd import numpy as np from sklearn.externals import joblib feat_file = 'C:\\Users\\DianaCarolina\\Google Drive\\Maestría\\datos\\indices_Diana\\all_type.xlsx' sites = {"Bosque":['5256', '5260'], "Rastrojo": ['5253', '5255'], "Pastizal": ['5257', '7125']} model=joblib.load("C:\\Users\\DianaCarolina\\Google Drive\\Maestría\\datos\\indices_Diana\\ecotyhmm13_3.pkl") nclasses = 13 for comp in range(nclasses): histData = [] types = [] col = [] for type in sites: df = pd.read_excel(feat_file, sheet_name=type, index_col=0) mdata=df.loc[df.iloc[:, 20] == comp, "Mes"] types.append(type) histData.append(mdata) if len(col) < 3: if type == "Bosque" and "green" not in col: col.append("green") elif type == "Rastrojo" and "orange" not in col: col.append("orange") elif type == "Pastizal" and "yellow" not in col: col.append("yellow") mclass = np.sum(np.array([model.gmms_[comp].weights_]).T * model.gmms_[comp].means_, 0) plt.figure() if not histData[0].empty or not histData[1].empty or not histData[2].empty: plt.subplot(2, 1, 1) n, bins, patches = plt.hist(histData, np.arange(0.5,13, 1), stacked=True, label= types, color = col, rwidth=0.8) plt.legend() plt.xticks(range(1,13), ("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", \ "Septiembre", "Octubre", "Noviembre", "Diciembre")) plt.title("Clase "+str(comp+1)+" de "+str(nclasses)) plt.subplot(2, 1, 2) plt.stem(mclass) plt.xticks(range(14), list(df.loc[:, "M":"Salida2_4"])) plt.title("Medias de características para la clase") plt.show() plt.close() # 新增:关闭当前窗口,让程序继续执行下一次循环
额外小建议
- 如果你需要所有图表同时打开不关闭,方案2会更适合;如果看完一个关一个,方案1最省心。
- 可以通过
print(plt.get_backend())查看当前Matplotlib的后端,PyCharm社区版推荐用TkAgg或Qt5Agg这类交互式后端。 - 循环里重复读取Excel文件效率很低,建议提前把所有数据读入内存再循环处理,能大幅提升运行速度哦!
内容的提问来源于stack exchange,提问作者dduque
相关产品推荐
相关产品推荐

