Автоматическое определение доступности дисплея с помощью matplotlib
Я генерирую рисунки matplotlib в сценарии, который я запускаю поочередно с графическим отображением или без него. Мне бы хотелось, чтобы скрипт настраивался автоматически: при отображении он должен отображать цифры в интерактивном режиме, а без отображения - просто сохранять их в файл.
Из ответа на вопрос " Создание графиков matplotlib без работающего X-сервера" я узнал, что можно использовать бэкэнд Agg для неинтерактивного построения графиков.
Итак, я пытаюсь с этим кодом:
import matplotlib
try:
import matplotlib.pyplot as plt
fig = plt.figure()
havedisplay = True
except:
matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig = plt.figure()
havedisplay = False
# do the plotting
if havedisplay:
plt.show()
else:
fig.savefig("myfig.png")
Это работает как исключение в случае с дисплеем. Тем не менее, без дисплея, вызов matplotlib.use
не действует, так как дисплей уже выбран. Понятно, что мне следует позвонить matplotlib.use
до import matplotlib.pyplot
, но тогда я не знаю, как проверить, доступен ли дисплей или нет.
Я также попробовал с экспериментальной функцией matplotlib.switch_backend
вместо matplotlib.use
, но это генерирует RuntimeError.
Есть ли у кого-то идеи, как заставить вышеуказанный код работать как задумано, или может предложить альтернативный способ определения, доступен ли дисплей для matplotlib или нет?
6 ответов
Вы можете непосредственно определить, есть ли у вас дисплей с модулем ОС в Python. в моем случае это
os.environ["DISPLAY"] ':0.0'
Код ниже работает для меня в Linux и Windows (если предполагается, что есть устройство отображения):
import os
import matplotlib
if os.name == 'posix' and "DISPLAY" not in os.environ:
matplotlib.use('Agg')
См. /questions/17984102/kak-ya-mogu-proverit-rabotayu-li-ya-na-windows-v-python/17984122#17984122.
Обратите внимание, что линия matplotlib.use('Agg')
должен появиться после первого импорта matplotlib
(в противном случае вы получите ошибку).
Попробуй это?
import matplotlib,os
r = os.system('python -c "import matplotlib.pyplot as plt;plt.figure()"')
if r != 0:
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig = plt.figure()
fig.savefig('myfig.png')
else:
import matplotlib.pyplot as plt
fig = plt.figure()
plt.show()
Комбинируя оба подхода выше, вы получите, возможно, лучшее решение:
havedisplay = "DISPLAY" in os.environ
if not havedisplay:
exitval = os.system('python -c "import matplotlib.pyplot as plt; plt.figure()"')
havedisplay = (exitval == 0)
Причина этого комбо состоит в том, что время выполнения os.system
Команда может занять некоторое время. Поэтому, когда вы уверены, что у вас есть дисплей (судя по os.environ
значение), вы можете сэкономить это время. С другой стороны, даже если DISPLAY
ключ не установлен в os.environ
переменная, есть вероятность того, что методы печати будут работать с графическим интерфейсом (например, при использовании командной строки Windows).
Решение, предложенное @Oz123, сгенерировало синтаксическую ошибку для меня. Тем не менее, я смог легко обнаружить дисплей с помощью:
import os
havedisplay = "DISPLAY" in os.environ
#plotting...
В любом случае, это было самое простое, что я мог найти.
При использовании графического интерфейса пользователя у объекта figure есть метод show(), вы можете использовать его для переключения:
import matplotlib
#matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig = plt.figure()
havedisplay = False
if hasattr(fig, "show"):
plt.show()
else:
print "save fig"
fig.savefig("myfig.png")
import os
have_display = bool(os.environ.get('DISPLAY', None))
have_display
Неверно, если DISPLAY
не находится в среде или является пустой строкой. в противном случае это правда