Python обнаружил ошибку сервера x при показе изображения - PullRequest
0 голосов
/ 03 января 2019

Есть ли способ перехватить исключение X-сервера в Python при использовании Image.show ()?

Когда я пытаюсь показать изображение через ssh-соединение, когда я не использовал опцию -X или -Y, я хочу прекратить запуск программы, так как она будет выполняться в цикле, так что нет смысла при попытке загрузить больше изображений.
Это отображает ошибку display.im6: unable to open X server ' @ error/display.c/DisplayImageCommand/428.'
Но не представляется возможным уловить это, так как я думаю, что ОС показывает эту ошибку после выполнения вызова PIL Image.show ().

from PIL import Image
img = Image.open(img_name)
try:
    img.show()
except Exception as e:
    print(e)
    sys.exit()

Вызов никогда не переходит на исключение.

1 Ответ

0 голосов
/ 03 января 2019

Как видно из кода PIL на https://pillow.readthedocs.io/en/5.3.x/_modules/PIL/ImageShow.html, метод show в изображениях в конечном итоге вызовет os.system с эвристически определенной командой для отображения изображения.Проблема, как можно видеть здесь, заключается в том, что возвращаемое значение вызова os.system игнорируется, поэтому, даже если изображение не отображается, программа никогда не узнает об этом.

Вы можете попробоватьmonkey-patching os.system, чтобы вызвать ошибку, если оригинальная система os.system возвращает что-то отличное от нуля, и тогда у вас будет исключение.Однако, попробовав это таким образом, я заметил, что для моего средства просмотра по умолчанию он возвращает «0» в качестве кода выхода в любом случае, даже с неработающим дисплеем, поэтому его нельзя обнаружить с помощью «системы».Вам нужно было бы соединить os.system с функцией, которая сделает правильный вызов subprocess.Popen, и проверит не только код выхода, но также sdterr вызванной команды - она ​​начинает усложняться.

Итак, второй, более простой и, возможно, более безопасный путь - заставить вашу программу проверять содержимое переменной окружения DISPLAY.Если он пуст или недействителен, любая попытка использовать дисплей X будет неудачной:

import os

if not os.environ.get("DISPLAY"):
    raise RuntimeError("Display is not properly set. Aborting!")

Почему это так? Исторически PIL (исходный PIL, а не текущая поддерживаемая подушка)) show код был простым жестко закодированным вызовом xv - вероятно, он был найден полезным только для целей отладки владельцами исходных библиотек.Хотя сегодня это более изощренно, поиск подходящего внешнего зрителя среди пары (все еще жестко закодированных) опций никоим образом не является «интерфейсом первого класса».Я думаю, что это подходит для вашего описанного варианта использования, но для чего-то еще, возможно, первым вариантом будет перейти на matplotlib для отображения изображений в пользовательском интерфейсе, который лучше контролируется из кода Python, без необходимости прибегать кнаписать полный код GUI с помощью Qt или Tkinter.

...