Python, matplotlib. Installation dans un environnement virtuel avec redirection X11

Logo

Introduction

Sur Ubuntu, un script Python 3 exécutant Matplotlib pour afficher un graphique échoue avec l’erreur ci-dessous :

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()

L’erreur se produit dans un environnement virtuel Python 3.9 virtual environment. L’installation du package Matplotlib dans l’environnement virtuel a été réalisée sans encombres.

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

Quel est le problème et comment le résoudre ?

Diagnostic du problème

La fonction get_backend du package matplotlib donne la réponse :

import matplotlib
matplotlib.get_backend()
'agg'

Pour afficher la figure, matplotlib a besoin d’un "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 n’est pas un GUI backend.

Pour utiliser le GUI backend Tcl/Tk (TkAgg), Python a besoin du module tkinter. Si l’import échoue, la distribution Python n’est pas configurée correctement.

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'

Configuration de Python avec Tcl Tk

Distribution Python personnalisée (compilée)

Si la distribution source Python utilisée pour construire l’environnement virtuel a été compilée avec Tcl/Tk absent de la machine, pas le choix :

  • Une nouvelle distribution source Python est compilée avec Tcl/Tk installé.
  • L’environnement virtuel est reconstruit avec cette nouvelle distribution source Python.

1. Installer Tcl/Tk :

$ apt-get install tcl-dev tk-dev

2. Compiler la nouvelle distribution source Python. Tcl/Tk est installé, le module tkinter sera construit :

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

3. On peut vérifier que tkinter a été construit pour Python avec l’existence du fichier _tkinter.cpython-39-x86_64-linux-gnu.so dans le répertoire <installation dir Python 3.9>/lib/python3.9/lib-dynload/. Remplacer 39 et 3.9 par 3x et 3.x pour toute version Python 3.x.

4. L’environnement virtuel est reconstruit, matplotlib installé. Quand matplotlib est installé dans l’environnement virtuel, la librairie backend TkAgg correspondante est compilée : <dir virtual env>/lib/python3.9/site-packages/matplotlib/backends/_tkagg.cpython-39-x86_64-linux-gnu.so.

Distribution Python par défaut

Si le problème ne survient pas dans une distribution Python personnalisée, ni dans un environnement virtuel :

  • installer Tcl/Tk puis python-tk (Python 2) ou python3-tk (Python 3) selon la version de Python utilisée
    $ apt-get install tcl-dev tk-dev python-tk python3-tk
  • réinstaller matplotlib avec pip
    $ pip3 --no-cache-dir install -U --force-reinstall matplotlib

Comme pour les distributions personnalisées Python, les librairies nécessaires sont compilées/installées :

  • /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

Affichage de la figure matplotlib

Maintenant, le module tkinter peut être chargé et le backend GUI de matplotlib est le bon :

import tkinter

import matplotlib
matplotlib.get_backend()
'TkAgg'

La figure est correctement affichée avec la redirection X11 (SQLPAC - Ubuntu, afficher des fenêtres serveur X vers des hôtes clients Windows 10 avec Putty et XMing Server), no particular issue.

X11 forwarding Figure Matplotlib