添加Matplotlib绘图代码后Tkinter应用退出仍后台运行问题排查
问题:Tkinter窗口关闭后进程残留的原因分析
我开发了一个基于Tkinter的应用,原本通过window.destroy()可正常关闭。但添加某段Matplotlib绘图代码后,窗口虽关闭但进程仍在后台运行。此前实现相同功能的代码无此问题,经排查问题出在以下标注的代码块,请问原因是什么?
def plot_graph(f): fig_df_in = f fig_df_in["Week Number"] = pd.to_datetime(fig_df_in["Available For Harvest"]).dt.isocalendar().week fig_df_in = fig_df_in.loc[ (fig_df_in["Week Number"] == window.current_week)] fig_df_in = pd.pivot_table(fig_df_in, values="Acres", index="Available For Harvest", columns="RB#") lf = ttk.Labelframe(table_frame) lf.grid(row=5, column=0, padx=10, pady=16, columnspan=12) # problem seems to start here ax = fig_df_in.plot(kind="bar") fig = ax.get_figure() fig.set_size_inches(15.2, 4) ax.set_xlabel("Harvest Date") ax.set_ylabel("Acres") plt.xticks(rotation="horizontal") plt.legend(bbox_to_anchor=(1.10, 1), loc='upper right', borderaxespad=0) # and end here canvas = FigureCanvasTkAgg(fig, master=lf) canvas.get_tk_widget().grid(row=0, column=0)
原因与解决方法
问题根源
你混合使用了pandas绘图接口和Matplotlib的pyplot全局状态,导致进程残留:
- pandas的
plot()方法默认会借助pyplot创建全局的Figure和Axes对象 - 后续调用
plt.xticks()、plt.legend()这些pyplot全局方法时,会绑定到这个绘图上下文 - 即便你把Figure关联到Tkinter的画布,pyplot的全局状态里仍保留着对该Figure的引用,窗口销毁后Matplotlib的后台绘图进程无法正常终止,最终导致整个Python进程残留后台。
解决方法
方法一:完全使用Axes对象操作,避开pyplot全局方法
直接通过获取到的ax对象调用对应方法,替代plt.xxx的全局调用:
ax = fig_df_in.plot(kind="bar") fig = ax.get_figure() fig.set_size_inches(15.2, 4) ax.set_xlabel("Harvest Date") ax.set_ylabel("Acres") # 用ax的tick_params替代plt.xticks ax.tick_params(axis='x', rotation=0) # 用ax的legend方法替代plt.legend ax.legend(bbox_to_anchor=(1.10, 1), loc='upper right', borderaxespad=0)
方法二:显式清理pyplot的全局资源
在绘图完成后,手动关闭当前Figure,解除全局引用:
# 在canvas创建后添加 plt.close(fig)
或者给Tkinter窗口绑定关闭回调,在销毁前清理所有Matplotlib资源:
def on_closing(): plt.close('all') window.destroy() window.protocol("WM_DELETE_WINDOW", on_closing)
内容的提问来源于stack exchange,提问作者Patrick Bickle
相关产品推荐
相关产品推荐

