[Python] RuntimeError: Invalid DISPLAY variable

1.問題:在本地用matplotlib繪圖能夠,可是在ssh遠程繪圖的時候會報錯 RuntimeError: Invalid DISPLAY variablehtml

2.緣由:matplotlib的默認backend是TkAgg,而FltkAgg, GTK, GTKAgg, GTKCairo, TkAgg , Wx or WxAgg這幾個backend都要求有GUI圖形界面的,因此在ssh操做的時候會報錯.python

import matplotlib.pyplot as plt
Backend TkAgg is interactive backend. Turning interactive mode on.

plt.get_backend()
Out[3]: u'TkAgg'

3.解決方法:指定不須要GUI的backend(Agg, Cairo, PS, PDF or SVGwindows

import matplotlib.pyplot as plt
plt.switch_backend('agg')

4.源碼session

查看plt.switch_backend()的源碼實現和解析:app

def switch_backend(newbackend):
    """
    Switch the default backend.  This feature is **experimental**, and
    is only expected to work switching to an image backend.  e.g., if
    you have a bunch of PostScript scripts that you want to run from
    an interactive ipython session, you may want to switch to the PS
    backend before running them to avoid having a bunch of GUI windows
    popup.  If you try to interactively switch from one GUI backend to
    another, you will explode.

    Calling this command will close all open windows.
    """
    close('all')
    global _backend_mod, new_figure_manager, draw_if_interactive, _show
    matplotlib.use(newbackend, warn=False, force=True)
    from matplotlib.backends import pylab_setup
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()

 

查看matplotlib.use()的源碼:less

def use(arg, warn=True, force=False):
    """
    Set the matplotlib backend to one of the known backends.

    The argument is case-insensitive. *warn* specifies whether a
    warning should be issued if a backend has already been set up.
    *force* is an **experimental** flag that tells matplotlib to
    attempt to initialize a new backend by reloading the backend
    module.

    .. note::

        This function must be called *before* importing pyplot for
        the first time; or, if you are not using pyplot, it must be called
        before importing matplotlib.backends.  If warn is True, a warning
        is issued if you try and call this after pylab or pyplot have been
        loaded.  In certain black magic use cases, e.g.
        :func:`pyplot.switch_backend`, we are doing the reloading necessary to
        make the backend switch work (in some cases, e.g., pure image
        backends) so one can set warn=False to suppress the warnings.

    To find out which backend is currently set, see
    :func:`matplotlib.get_backend`.

    """
    # Lets determine the proper backend name first
    if arg.startswith('module://'):
        name = arg
    else:
        # Lowercase only non-module backend names (modules are case-sensitive)
        arg = arg.lower()
        name = validate_backend(arg)

    # Check if we've already set up a backend
    if 'matplotlib.backends' in sys.modules:
        # Warn only if called with a different name
        if (rcParams['backend'] != name) and warn:
            warnings.warn(_use_error_msg)

        # Unless we've been told to force it, just return
        if not force:
            return
        need_reload = True
    else:
        need_reload = False

    # Store the backend name
    rcParams['backend'] = name

    # If needed we reload here because a lot of setup code is triggered on
    # module import. See backends/__init__.py for more detail.
    if need_reload:
        reload(sys.modules['matplotlib.backends'])

 

參考:DISPLAY error matplotlib http://chewpichai.blogspot.com/2008/01/display-error-matplotlib.html 。原文可能被牆了,須要設法翻一下。ssh

原文內容:ui

DISPLAY error matplotlib
When error occur about this "$DISPLAY not set" when you run python code that use matplotlib this happened because your matplotlib backend is set to FltkAgg, GTK, GTKAgg, GTKCairo, TkAgg , Wx or WxAgg they required a GUI that why error occur.

To solve this you must specific other backend that not required GUI (Agg, Cairo, PS, PDF or SVG) when use matplotlib like this 

In code
import matplotlib matplotlib.use('Agg')
In command line use
-d option python subplot_demo.py -dAgg Remember when call savefig('filename') don't give it extension this will handle by backend that you specific e.g Agg will create file filename.png