Python, matplotlib. Installation in a virtual environment and X11 forwarding

Logo

Introduction

On Ubuntu, a Python 3 script running Matplotlib to display a graph fails with the following error :

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
myplot.py:4: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend,
so cannot show the figure.
  plt.show()

The error occurs in a Python 3.8 virtual environment. The installation of the Matplotlib package in the virtual environment was successful.

$ pip3 list
Package         Version
--------------- -------
matplotlib      3.4.2

What’s the issue and how to solve it ?

Diagnosing the issue

The function get_backend of the package matplotlib gives the answer :

import matplotlib
matplotlib.get_backend()
'agg'

To display the figure, matplotlib needs a GUI backend : Tcl Tk (TkAgg), Qt 4/5 (Qt4Agg, Qt5Agg)…

import matplotlib.rcsetup as rcsetup
print(rcsetup.all_backends)
['GTK3Agg', 'GTK3Cairo', 'MacOSX', 'nbAgg', 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo',
'TkAgg', 'TkCairo', 'WebAgg', 'WX', 'WXAgg', 'WXCairo',
'agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template']

agg is not a GUI backend.

To use the Tcl Tk GUI backend (TkAgg), Python needs the module tkinter. If the import fails, Python distribution is not configured properly.

import tkinter
  File "/opt/python/python-3.8/lib/python3.8/tkinter/__init__.py", line 36, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

Configuring Python with Tcl Tk

Customized Python distribution (compiled)

If the Python source distribution to build the virtual environment was compiled with Tcl/Tk missing on the host, no choice :

  • A new Python source distribution is compiled with Tcl/Tk installed.
  • The virtual environment is rebuilt with the updated Python source distribution.

1. Install Tcl/Tk :

$ apt-get install tcl-dev tk-dev

2. Compile the new Python source distribution. Tcl/Tk is installed, the tkinter module will be built :

$ ./configure --prefix=/opt/python/python-3.9.5 \
  --enable-optimizations \
  --with-system-ffi \
  --enable-ipv6
          
$ make   
$ make install

3. You can verify that tkinter has been built for Python by checking the existence of the file _tkinter.cpython-39-x86_64-linux-gnu.so in the directory <installation dir Python 3.9>/lib/python3.9/lib-dynload/ for Python 3.9. Replace 39 and 3.9 by 3x and 3.x for any Python 3.x version.

4. The virtual environment is rebuilt, matplotlib installed. When matplotlib is installed in the virtual environment, the matching TkAgg backend library is compiled : <dir virtual env>/lib/python3.9/site-packages/matplotlib/backends/_tkagg.cpython-39-x86_64-linux-gnu.so.

Default Python distribution

If the issue does not occur in a customized Python distribution, nor virtual environment :

  • install Tcl/Tk and then python-tk (Python 2) or python3-tk (Python 3) depending on the used Python version
    $ apt-get install tcl-dev tk-dev python-tk python3-tk
  • reinstall matplotlib using pip
    $ pip3 --no-cache-dir install -U --force-reinstall matplotlib

As with custom Python distributions, needed libraries are compiled/installed :

  • /usr/lib/python3.6/lib-dynload/_tkinter.cpython-36m-x86_64-linux-gnu.so
  • /usr/lib/python3.6/site-packages//matplotlib/backends/_tkagg.cpython-39-x86_64-linux-gnu.so

Running the matplotlib figure

Now, the tkinter module can be loaded and the matplotlib GUI backend is the right one :

import tkinter

import matplotlib
matplotlib.get_backend()
'TkAgg'

The figure is well displayed using X11 forwarding (SQLPAC - Ubuntu, how to display server windows on Windows 10 client hosts with Putty and XMing Server), no particular issue.

X11 forwarding Matplotlib figure