Автоматическое определение доступности дисплея с помощью 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 не находится в среде или является пустой строкой. в противном случае это правда

Другие вопросы по тегам