Генерация PNG с помощью matplotlib, когда DISPLAY не определено
Я пытаюсь использовать networkx с Python. Когда я запускаю эту программу, она получает эту ошибку. Чего-то не хватает?
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
Traceback (most recent call last):
File "graph.py", line 13, in <module>
nx.draw(G)
File "/usr/lib/pymodules/python2.5/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
Теперь я получаю другую ошибку:
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
matplotlib.use('Agg')
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
/usr/lib/pymodules/python2.5/matplotlib/__init__.py:835: UserWarning: This call to matplotlib.use() has no effect
because the the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
File "graph.py", line 15, in <module>
nx.draw(G)
File "/usr/lib/python2.5/site-packages/networkx-1.2.dev-py2.5.egg/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
Теперь я получаю другую ошибку:
#!/usr/bin/env python
import networkx as nx
import matplotlib
import matplotlib.pyplot
import matplotlib.pyplot as plt
matplotlib.use('Agg')
G=nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3,4,5,6,7,8,9,10])
#nx.draw_graphviz(G)
#nx_write_dot(G, 'node.png')
nx.draw(G)
plt.savefig("/var/www/node.png")
/usr/lib/pymodules/python2.5/matplotlib/__init__.py:835: UserWarning: This call to matplotlib.use() has no effect
because the the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
if warn: warnings.warn(_use_error_msg)
Traceback (most recent call last):
File "graph.py", line 15, in <module>
nx.draw(G)
File "/usr/lib/python2.5/site-packages/networkx-1.2.dev-py2.5.egg/networkx/drawing/nx_pylab.py", line 124, in draw
cf=pylab.gcf()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 276, in gcf
return figure()
File "/usr/lib/pymodules/python2.5/matplotlib/pyplot.py", line 254, in figure
**kwargs)
File "/usr/lib/pymodules/python2.5/matplotlib/backends/backend_tkagg.py", line 90, in new_figure_manager
window = Tk.Tk()
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1650, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
13 ответов
Основная проблема заключается в том, что (в вашей системе) matplotlib выбирает бэкэнд с использованием x по умолчанию. У меня была такая же проблема на одном из моих серверов. Решением для меня было добавить следующий код в место, которое будет прочитано перед любым другим импортом pylab / matplotlib /pyplot:
import matplotlib
# Force matplotlib to not use any Xwindows backend.
matplotlib.use('Agg')
Альтернатива - установить его в вашем.matplotlibrc.
Так же, как дополнение к ответу Рейно.
Постоянный способ решить эту проблему - отредактировать файл.matplotlibrc. Найти через
>>> import matplotlib
>>> matplotlib.matplotlib_fname()
# This is the file location in Ubuntu
'/etc/matplotlibrc'
Затем измените бэкэнд в этом файле на backend : Agg
, Вот и все.
Чистый ответ - потратить немного времени на правильную подготовку вашей среды исполнения.
Первая техника, которую вы должны подготовить - это использовать matplotlibrc
файл, как мудро рекомендовал Крис Q., настройка
backend : Agg
в этом файле. Вы даже можете контролировать - без изменений кода - как и где matplotlib ищет и находит matplotlibrc
файл
Второй метод подготовки среды выполнения - использование MPLBACKEND
Переменная окружения (и сообщите своим пользователям, чтобы использовать ее):
export MPLBACKEND="agg"
python <program_using_matplotlib.py>
Это удобно, потому что вам даже не нужно предоставлять другой файл на диске, чтобы это работало. Я использовал этот подход, например, для тестирования в условиях непрерывной интеграции и запуска на удаленных машинах, которые не имеют дисплеев.
Жесткое программирование вашего бэкэнда matplotlib для "Agg" в вашем коде Python похоже на врезание квадратного колышка в круглое отверстие большим молотком, когда вместо этого вы могли просто сказать matplotlib, что это должно быть квадратное отверстие.
Я получил ошибку при использовании matplotlib через Spark. matplotlib.use('Agg')
не работает для меня В конце концов, следующий код работает для меня. Больше здесь
import matplotlib.pyplot as plt.
plt.switch_backend('agg')
Я просто повторю то, что сказал @Ivo Bosticky, что можно пропустить. Поместите эти строки в ОЧЕНЬ начало файла py.
import matplotlib
matplotlib.use('Agg')
Или можно получить ошибку
*/usr/lib/pymodules/python2.7/matplotlib/__init__.py:923: UserWarning: этот вызов matplotlib.use() не имеет никакого эффекта потому что бэкэнд уже был выбран; matplotlib.use() должен быть вызван * перед * pylab, matplotlib.pyplot,*
Это решит все проблемы с отображением
Я обнаружил, что этот фрагмент хорошо работает при переключении между средами X и no-X.
import os
import matplotlib as mpl
if os.environ.get('DISPLAY','') == '':
print('no display found. Using non-interactive Agg backend')
mpl.use('Agg')
import matplotlib.pyplot as plt
При входе на сервер для выполнения кода используйте вместо этого:
ssh -X username@servername
-X
избавит от ошибки, связанной с отсутствием отображаемого имени и переменной $DISPLAY
:)
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
Меня устраивает.
На какой ты системе? Похоже, у вас есть система с X11, но переменная окружения DISPLAY не была правильно установлена. Попробуйте выполнить следующую команду и перезапустить программу:
export DISPLAY=localhost:0
Еще одна вещь, которую нужно проверить, - авторизован ли ваш текущий пользователь для подключения к дисплею X. В моем случае root не мог этого сделать, и matplotlib жаловался с той же ошибкой.
user@debian:~$ xauth list
debian/unix:10 MIT-MAGIC-COOKIE-1 ae921efd0026c6fc9d62a8963acdcca0
root@debian:~# xauth add debian/unix:10 MIT-MAGIC-COOKIE-1 ae921efd0026c6fc9d62a8963acdcca0
root@debian:~# xterm
источник: http://www.debian-administration.org/articles/494 https://debian-administration.org/article/494/Getting_X11_forwarding_through_ssh_working_after_running_su
Чтобы ваш код переносился на Windows, Linux и OSX, а также на системы с дисплеями и без них, я бы предложил следующий фрагмент:
import matplotlib
import os
# must be before importing matplotlib.pyplot or pylab!
if os.name == 'posix' and "DISPLAY" not in os.environ:
matplotlib.use('Agg')
# now import other things from matplotlib
import matplotlib.pyplot as plt
Для Google Cloud Machine Learning Engine:
import matplotlib as mpl
mpl.use('Agg')
from matplotlib.backends.backend_pdf import PdfPages
А затем распечатать в файл:
#PDF build and save
def multi_page(filename, figs=None, dpi=200):
pp = PdfPages(filename)
if figs is None:
figs = [mpl.pyplot.figure(n) for n in mpl.pyplot.get_fignums()]
for fig in figs:
fig.savefig(pp, format='pdf', bbox_inches='tight', fig_size=(10, 8))
pp.close()
и создать PDF:
multi_page(report_name)
import matplotlib
matplotlib.use('Agg')
работал для меня, пока я напрямую вызывал функции/код построения графика. Но если вы используете
from joblib import Parallel, delayed
Parallel
а также
delayed
модули для распараллеливания вашего кода, вам нужно добавить
matplotlib.rcParams.update({'backend': 'Agg'})
строка внутри вашей функции, чтобы
agg
бэкэнд для работы.