使用Matplotlib绘图时触发Tkinter错误,请求技术协助
_tkinter.TclError: no display name and no $DISPLAY environment variable错误 先还原你遇到的完整错误栈:
回溯(最近的调用最后):
File "file_client.py", line 117, in
plot_graph(result)
File "file_client.py", line 81, in plot_graph
plt.scatter(list(time_dict.keys()), list(time_dict.values()))
File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 3364, in scatter
ax = gca()
File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 962, in gca
return gcf().gca(**kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 592, in gcf
return figure()
File "/usr/lib/python3/dist-packages/matplotlib/pyplot.py", line 539, in figure
**kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/backend_bases.py", line 171, in new_figure_manager
return cls.new_figure_manager_given_figure(num, fig)
File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_tkagg.py", line 1049, in new_figure_manager_given_figure
window = Tk.Tk(className="matplotlib")
File "/usr/lib/python3.6/tkinter/init.py", line 2023, in init
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
这个问题我太熟了!本质就是Matplotlib默认的Tkinter后端需要图形显示环境,但你运行代码的环境(比如远程服务器、无桌面的Linux系统、不带X11转发的SSH会话)里没有提供可用的显示器,所以就抛出这个错误了。
下面给你三个实用的解决办法,根据你的使用场景选就行:
方法1:切换为非交互式后端(推荐服务器环境使用)
直接在代码开头指定Matplotlib使用不需要显示的后端,比如Agg,这样就能直接生成图片文件而不需要弹出窗口:
# 一定要在导入pyplot之前设置后端! import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt # 你的绘图代码不变 plt.scatter(list(time_dict.keys()), list(time_dict.values())) # 因为没有图形界面,要把图保存成文件 plt.savefig('transfer_time_plot.png') # 记得关闭绘图释放资源 plt.close()
⚠️ 重点:matplotlib.use()必须放在import matplotlib.pyplot as plt之前,不然设置不会生效!
方法2:开启X11转发(适合远程连接且本地有图形界面)
如果你是通过SSH连接服务器,并且本地电脑有图形界面(比如Windows带Xming、Mac自带X11),可以开启X11转发来让服务器把绘图窗口显示到本地:
- 连接服务器时加上
-X参数:
ssh -X your_username@your_server_ip
- 连接后检查
DISPLAY变量是否自动设置,要是没设置就手动导出:
export DISPLAY=:0.0
之后再运行你的Python脚本,就能在本地看到Matplotlib的绘图窗口了。
方法3:适配Jupyter环境
如果是在Jupyter Notebook/Lab里运行代码,直接用魔法命令切换到交互式后端即可:
# 静态显示用这个 %matplotlib inline # 想要交互式控件(比如缩放、平移)用这个 # %matplotlib notebook import matplotlib.pyplot as plt plt.scatter(list(time_dict.keys()), list(time_dict.values())) plt.show()
要是你只是需要生成图片文件,方法1绝对是最省心的选择,完全不需要依赖图形环境;如果需要实时查看绘图窗口,就根据场景选方法2或3。
内容的提问来源于stack exchange,提问作者JackLalane1

