Jak zmienić backendy w matplotlib / Python

90

Zmagam się z następującym problemem. Muszę wygenerować raporty składające się ze zbioru wykresów. Wszystkie te wykresy, z wyjątkiem jednego, są tworzone przy użyciu domyślnego zaplecza Matplotlib (TkAgg). Jeden wykres musi zostać utworzony przy użyciu zaplecza Cairo, ponieważ kreślę wykres igraph, który można wykreślić tylko za pomocą Cairo.

Problem polega na tym, że nie mogę zmienić backendów w locie, na przykład nie działa:
matplotlib.pyplot.switch_backend('cairo.png') (wiem, że funkcja switch_backend jest eksperymentalna)

i próbowałem również, matplotlib.use("cairo.png")ale prowadzi to do problemów z importem, ponieważ matplotlib.use("cairo.png")instrukcja powinna pojawić się przed importem matplotlib.pyplot. ale potrzebuję dwóch różnych backendów w trakcie życia skryptu.

Więc moje pytanie brzmi: czy ktoś ma fragment kodu, który pokazuje, jak przełączyć zaplecze w Matplotlib?

Dzięki wielkie!

AKTUALIZACJA: Napisałem fragment, który ładuje matplotlib, pokazuje domyślny backend, zwalnia matplotlib, przeładowuje go i zmienia backend:

import matplotlib
import matplotlib.pyplot as plt
import sys
print matplotlib.pyplot.get_backend()

modules = []
for module in sys.modules:
    if module.startswith('matplotlib'):
        modules.append(module)

for module in modules:
    sys.modules.pop(module)

import matplotlib
matplotlib.use("cairo.png")
import matplotlib.pyplot as plt

print matplotlib.pyplot.get_backend()

ale czy to naprawdę jest sposób na zrobienie tego?

AKTUALIZACJA 2: Wczoraj miałem poważne zamrożenie mózgu ... Prostym i najbardziej oczywistym rozwiązaniem jest użycie backendu Cairo do wszystkich wykresów i nie przełączanie backendu w ogóle :)

AKTUALIZACJA 3: Właściwie nadal jest to problem, więc każdy, kto wie, jak dynamicznie przełączać backendy matplotlib ... proszę opublikować swoją odpowiedź.

DrDee
źródło
Jest pyplot.switch_backends(). To może nie działać w Twoim przypadku.
jfs

Odpowiedzi:

60

Sześć lat później natknąłem się na podobny problem, próbując zdecydować, który z nich backendbył dostępny.
Uwaga, patrz Zastrzeżenia - poniżej

Ten fragment kodu działa dobrze dla mnie:

import matplotlib
gui_env = ['TKAgg','GTKAgg','Qt4Agg','WXAgg']
for gui in gui_env:
    try:
        print "testing", gui
        matplotlib.use(gui,warn=False, force=True)
        from matplotlib import pyplot as plt
        break
    except:
        continue
print "Using:",matplotlib.get_backend()

Using: GTKAgg

Jak możesz wywnioskować, zamiana pliku backendjest tak prosta, jak ponowne zaimportowanie matplotlib.pyplotpo wymuszeniu nowegobackend

matplotlib.use('WXAgg',warn=False, force=True)
from matplotlib import pyplot as plt
print "Switched to:",matplotlib.get_backend()

Switched to: WXAgg

Dla tych, którzy nadal mają problemy, ten kod wydrukuje:
listę backendów Non Gui;
lista backendów Gui;
a następnie spróbuj użyć każdego zaplecza Gui, aby sprawdzić, czy jest obecny i działa.

import matplotlib
gui_env = [i for i in matplotlib.rcsetup.interactive_bk]
non_gui_backends = matplotlib.rcsetup.non_interactive_bk
print ("Non Gui backends are:", non_gui_backends)
print ("Gui backends I will test for", gui_env)
for gui in gui_env:
    print ("testing", gui)
    try:
        matplotlib.use(gui,warn=False, force=True)
        from matplotlib import pyplot as plt
        print ("    ",gui, "Is Available")
        plt.plot([1.5,2.0,2.5])
        fig = plt.gcf()
        fig.suptitle(gui)
        plt.show()
        print ("Using ..... ",matplotlib.get_backend())
    except:
        print ("    ",gui, "Not found")

Ostrzeżenia: zmiany w matplotlib od wersji 3.3.0

  • Nazwa pierwszego parametru matplotlib.use została zmieniona z arg na backend (ma znaczenie tylko w przypadku przekazywania przez słowo kluczowe).
  • Parametr warn z matplotlib.use został usunięty. Niepowodzenie przełączenia zaplecza będzie teraz zawsze powodować błąd ImportError, jeśli ustawiono siłę; złap ten błąd, jeśli to konieczne.
  • Wszystkie parametry matplotlib.use z wyjątkiem pierwszego są teraz tylko słowami kluczowymi.
Rolf Saksonii
źródło
Dzięki! To działało świetnie, pomagając mi znaleźć odpowiedni back-end dla tego przykładu: stackoverflow.com/questions/11874767/ ...
James Nelson
Rolf z Saksonii, LOL bardzo pomocny, wciąż dostaję odpowiedzi na posty na Ubuntu i Androida sprzed prawie dekady.
James Nelson
warn=FalseArgumentem nie jest już dostępny.
not2qubit
@ not2qubit Noted - thanks. Dodano ostrzeżenia.
Rolf z Saksonii
37

Istnieje funkcja „eksperymentalna”:

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

zaczerpnięte z matplotlib doc .

Przełącz domyślny backend na newbackend. Ta funkcja jest eksperymentalna i oczekuje się, że będzie działać tylko przy przełączaniu na zaplecze graficzne. Na przykład, jeśli masz kilka skryptów PostScript, które chcesz uruchomić z interaktywnej sesji ipython, możesz przełączyć się na zaplecze PS przed ich uruchomieniem, aby uniknąć wyskakujących okienek GUI. Jeśli spróbujesz interaktywnie przełączyć się z jednego zaplecza GUI na inny, wybuchniesz. Wywołanie tego polecenia spowoduje zamknięcie wszystkich otwartych okien.

oyo
źródło
Nierozpoznany ciąg backendu „newbackend”. Co powinienem zrobić?
TSR
5
@TSR Zastąp `` newbackend '' zapleczem GUI, takim jak `` Qt4Agg ''
YashTD,
14

Dlaczego nie skorzystać po prostu z funkcji reloadwbudowanej ( importlib.reloadw Pythonie 3)?

import matplotlib
matplotlib.use('agg')

matplotlib = reload(matplotlib)
matplotlib.use('cairo.png')
fredbaba
źródło
Ponieważ nie możesz ponownie załadować matplotlib i matplotlib.pyplot? A może po prostu mówisz, że wycięty kod jest niekompletny?
fredbaba
Hmm. Właściwie mogło to być dziwactwo IPythona. Wydaje się, że działa dobrze w zwykłej konsoli.
Mad Physicist
1
Myślę, że to jest przykład, który pokazuje, że to nie działa: python -c "import matplotlib.pyplot as plt; import matplotlib; from importlib import reload; matplotlib = reload(matplotlib); matplotlib.use('Agg')"Czy to prawda?
Lukas
6

Więc nie jestem do końca pewien, czy tego właśnie szukasz.

Możesz zmienić swój backend za pomocą pliku matplotlibrc, który zawiera określone konfiguracje dla twojego matplotlib.

W swoim skrypcie możesz umieścić:

matplotlib.rcParams['backend'] = 'TkAgg' 

lub coś w tym rodzaju, aby przełączać się między backendami.

funkcja pomocnicza
źródło
2
Rzeczywiście, możesz określić backend w swoim słowniku rcParams, ale to nie rozwiązuje problemu przełączania się z jednego zaplecza na inny.
DrDee
możesz również ustawić domyślny backend w pliku konfiguracyjnym, który jest pobierany przez matplotlib:~/.config/matplotlib/matplotlibrc
scrutari
4

W moim przypadku (Windows 10 + python 3.7) pierwsza odpowiedź autorstwa @Rolfa z Saksonii nie zadziałała zbyt dobrze. Zamiast wypróbowywać wszystkie dostępne środowiska i konfigurować jedno z nich na początku, czyli zaraz potem

    import matplotlib

Musiałem zmienić środowisko z „Agg” na „TkAgg” za pomocą

    matplotlib.use('TKAgg',warn=False, force=True)

tuż przed kodem, w którym wykreśliłem, tj.

    import matplotlib.pyplot as plt
    fig = plt.figure()
    # AND SO ON....
Pe Dro
źródło
2

Aby trwale zmienić backend, możesz użyć tego:

  1. Najpierw zlokalizuj matplotlibrcplik:

    import matplotlib
    
    matplotlib.matplotlib_fname()
    # '/Users/serafeim/.matplotlib/matplotlibrc'
    
  2. Otwórz terminal i wykonaj:

    cd /Users/serafeim/.matplotlib/
    ls
    
  3. Edytuj plik (jeśli nie istnieje, użyj tego polecenia: touch matplotlibaby go utworzyć):

    vim matplotlibrc
    
  4. Dodaj tę linię i zapisz:

    backend: TkAgg
    
seralouk
źródło
1

Możesz także mieć inny proces w Pythonie, który tworzy ten wykres, być może przy pomocy pickle lub joblib .

Ken Arnold
źródło
0

Jeśli używasz konsoli IPython (w tym w Spyder), możesz użyć wbudowanych magicznych poleceń, aby szybko przełączać backendy, np:

%matplotlib qt

Uzyskaj listę dostępnych backendów do użycia z poleceniem:

%matplotlib --list

Dostępne backendy matplotlib: [„tk”, „gtk”, „gtk3”, „wx”, „qt4”, „qt5”, „qt”, „osx”, „nbagg”, „notebook”, „agg”, „ svg ”,„ pdf ”,„ ps ”,„ inline ”,„ ipympl ”,„ widget ”]

Mike T.
źródło
0

Extra Info

Chociaż każdy pokazuje swoje ulubione zaplecze, dość kłopotliwe jest ustalenie, co należy zainstalować i jakie są wymagania. Przynajmniej wtedy, gdy spróbujesz zrozumieć ogólnie zagmatwaną i technokratyczną dokumentację. Dzisiaj przeprowadziłem kilka eksperymentów i myślę, że znalazłem najprostsze rozwiązania dla każdego zaplecza, aby móc drukować za pomocą matplotlib w systemie Windows i przy użyciu Py3.8.5 (bez wbudowanego Qt). Oto moje ustalenia:

#--------------------------------------
# Installing the matplotlib backends
#--------------------------------------
# https://matplotlib.org/users/installing.html

pip install pycairo                     # [1] Cairo :   GTK3 based backend (replaces: cairocffi)    [1.2 Mb]
#pip install mplcairo                   # [1] Cairo :   Easy & Specific for matplotlib              [1.7 Mb]
#pip install PyQt5                      # [2] Qt5   :   Require: Qt's qmake tool                    []
pip install PySide2                     # [3] Qt5   :   Require: shiboken2 & Clang lib bindings     [136 Mb]
pip install wxPython                    # [4] WxAgg :   ??                                          [18.1 Mb]
pip install tornado                     # [5] WebAgg:   Require: pycurl,twisted,pycares ??          [422 kb]

Oto linki do wszystkich tych PyPi lub repozytoriów:

[1] https://pypi.org/project/pycairo/       # Requires GTK3+: https://www.gtk.org/
[1] https://pypi.org/project/mplcairo/      # https://github.com/matplotlib/mplcairo
[2] https://pypi.org/project/PyQt5/         # 
[3] https://pypi.org/project/PySide2/       # 
[4] https://pypi.org/project/wxPython/      # https://github.com/wxWidgets/Phoenix/
[4] https://github.com/wxWidgets/wxWidgets/releases
[5] https://pypi.org/project/tornado/       # https://github.com/tornadoweb/tornado

Jednak, co było bardzo zaskakujące, biorąc pod uwagę ogromną ilość dokumentacji dotyczącej używania Tcl/Tki tkinterpakietów dla Pythona, nie byłem w stanie go zainstalować ani znaleźć żadnych przydatnych instrukcji, jak zaimportować bibliotekę DLL do Pythona. (W przypadku Linuksa jest to trywialne, ponieważ po prostu używasz menedżera pakietów systemu operacyjnego apt-get install <tk-what-not>, ale ta opcja nie jest dostępna dla systemu Windows, ani nie ma żadnego prostego odpowiednika. Oto lista wielu różnych plików binarnych, które możesz uzyskać.

[6] http://www.bawt.tcl3d.org/download.html                 # Use Tcl-Pure (no additional packages)
[6] https://www.magicsplat.com/tcl-installer/index.html     # 
[6] https://www.irontcl.com/                                # 
[6] https://www.activestate.com/products/tcl/downloads/     # 
[6] http://tclkits.rkeene.org/fossil/wiki/Downloads         # 
[6] http://kitcreator.rkeene.org/kitcreator                 # 

Może ktoś może mnie oświecić, jak zaimportować którekolwiek z nich do Pythona?


What backends are available and where?

Oświećmy się następującymi jednowierszowymi:

python.exe -c "import matplotlib as m; help(m);"
python.exe -c "import matplotlib as m; print('I: {}\nN: {}'.format(m.rcsetup.interactive_bk,m.rcsetup.non_interactive_bk));"

# I: ['GTK3Agg', 'GTK3Cairo', 'MacOSX', 'nbAgg', 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo', 'TkAgg', 'TkCairo', 'WebAgg', 'WX', 'WXAgg', 'WXCairo']
# N: ['agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template']

python.exe -c "import matplotlib as m; p=m.get_backend();print('current backend is:',p);"
# agg

python.exe -c "import matplotlib as m; p=m.matplotlib_fname(); print('The matplotlibrc is located at:\n',p);"
# C:\Python38\lib\site-packages\matplotlib\mpl-data\matplotlibrc

Setting the back-end

Zgodnie z dokumentacją: istnieją 3 sposoby konfiguracji zaplecza:

  1. Ustawienie parametru rcParams["backend"](domyślnie: 'agg') w pliku matplotlibrc
  2. Ustawienie MPLBACKENDzmiennej środowiskowej (powłoki)
  3. Korzystanie z funkcji matplotlib.use()

Using the backend

Wreszcie, aby użyć dostępnego zaplecza, wystarczy zrobić to:

import matplotlib 
#matplotlib.use('tkagg', force=True)        # Agg rendering to a Tk canvas
#matplotlib.use('wxcairo', force=True)      # Cairo rendering to a wxWidgets canvas
#matplotlib.use('wxagg', force=True)        # Agg rendering to a wxWidgets canvas
matplotlib.use('webagg', force=True)        # On show() will start a tornado server with an interactive figure.

#matplotlib.use('qt5cairo', force=True)     # Cairo rendering to a Qt5 canvas
#matplotlib.use('qt5agg', force=True)       # Agg rendering to a Qt5 canvas

import matplotlib.pyplot as plt
not2qubit
źródło