Python 为什么这可以解决 matplotlib 的“无 $DISPLAY 环境”问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29217543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does this solve the 'no $DISPLAY environment' issue with matplotlib?
提问by Gabriel
When running a code that uses the matplotlib
library in my desktop PC, I have no issues using the line:
matplotlib
在我的台式 PC 中运行使用该库的代码时,使用以下行没有任何问题:
import matplotlib.pyplot as plt
far down the code, which is where I actually use the plotting functions.
在代码的深处,这是我实际使用绘图函数的地方。
If I run the code in a server though it will only work if I import matplotlib
before, and force it to use the Agg
backend. I.e., I have to add the following lines to the beginning of the code:
如果我在服务器中运行代码,但它只会在我matplotlib
之前导入时才有效,并强制它使用Agg
后端。即,我必须将以下行添加到代码的开头:
import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('Agg')
(see this answerwhere this is explained). Otherwise the code will crash with TclError: no display name and no $DISPLAY environment variable
(see this questionfor example).
(请参阅此答案,其中解释了这一点)。否则代码将崩溃TclError: no display name and no $DISPLAY environment variable
(例如,请参阅此问题)。
The question is: why do I need to do this? The solution works perfectly, but I don't know why I don't have to do this in my desktop PC but I absolutely must when the code runs in the server.
问题是:为什么我需要这样做?该解决方案完美无缺,但我不知道为什么我不必在台式机中执行此操作,但是当代码在服务器中运行时我绝对必须这样做。
采纳答案by ali_m
X11 follows a client/server model, where the X server accepts requests for graphical output from client applications (e.g. interactive matplotlib sessions), and sends back user input from the keyboard, mouse etc. In order for this model to work, client applications need to know which X server to send their requests to. This is controlled by the $DISPLAY
environment variable. In the case where you are connecting to a remote X session (for example over an SSH connection), the $DISPLAY
variable in your remote session needs to point to your local X server.
X11 遵循客户端/服务器模型,其中 X 服务器接受来自客户端应用程序(例如交互式 matplotlib 会话)的图形输出请求,并从键盘、鼠标等发回用户输入。 为了使该模型工作,客户端应用程序需要知道将请求发送到哪个 X 服务器。这是由$DISPLAY
环境变量控制的。如果您连接到远程 X 会话(例如通过 SSH 连接),$DISPLAY
远程会话中的变量需要指向本地 X 服务器。
The $DISPLAY
variable is structured like this:
该$DISPLAY
变量的结构是这样的:
hostname:displaynumber.screennumber
Not all parts may be present - the hostname is usually omitted for local sessions, and the screen number is also omitted if there is only one screen. In a local terminal session on laptop, my $DISPLAY
looks like this:
并非所有部分都可能存在 - 本地会话通常会省略主机名,如果只有一个屏幕,也会省略屏幕编号。在笔记本电脑上的本地终端会话中,我$DISPLAY
看起来像这样:
alistair@laptop:~$ echo $DISPLAY
:0
Provided that the remote server also supports X11, it's possible to open graphical windows on the remote machine and have them appear on your local machine using X11 forwarding. For an SSH connection you do this by passing the -X
(or -Y
) flag.
如果远程服务器也支持 X11,就可以在远程机器上打开图形窗口,并使用X11 forwarding 将它们显示在您的本地机器上。对于 SSH 连接,您可以通过传递-X
(或-Y
) 标志来完成此操作。
For example:
例如:
alistair@laptop:~$ ssh -X [email protected]
alistair@workstation:~$ echo $DISPLAY
localhost:10.0
The remote SSH server should take care of setting the $DISPLAY
variable appropriately when you open the connection. In this particular case, localhost:10.0
is actually a 'proxy' X11 server running on the remote machine that listens on display 10 and relays commands to your local X server over the SSH connection (take a look at thisif you're interested in the details).
$DISPLAY
当您打开连接时,远程 SSH 服务器应该负责适当地设置变量。在这种特殊情况下,localhost:10.0
实际上是一个运行在远程机器上的“代理”X11 服务器,它在显示器 10 上侦听并通过 SSH 连接将命令中继到您的本地 X 服务器(如果您对详细信息感兴趣,请查看此内容) .
Now you should be able to start a remote IPython session, import matplotlib using an interactive backend, and create plot windows which will then appear on your local machine. Since your keyboard/mouse input and the display output are now passing over an encrypted network connection, the plot windows will be less responsive than you're used to for a local session.
现在您应该能够启动远程 IPython 会话,使用交互式后端导入 matplotlib,并创建绘图窗口,然后这些窗口将显示在您的本地计算机上。由于您的键盘/鼠标输入和显示输出现在通过加密的网络连接传递,因此绘图窗口的响应速度将比您在本地会话中使用的响应速度慢。
Another word of warning: if you have an IPython session open with an interactive matplotlib session running it is impossible to close the SSH connection without killing the IPython process. I also sometimes call matplotlib.use("Agg")
before I start a long-running process that imports matplotlib - that way I can disconnect from the remote server without killing the process.
另一个警告:如果您打开一个 IPython 会话并运行交互式 matplotlib 会话,则不可能在不终止 IPython 进程的情况下关闭 SSH 连接。我有时也会matplotlib.use("Agg")
在开始导入 matplotlib 的长时间运行的进程之前调用- 这样我就可以在不终止进程的情况下与远程服务器断开连接。