Найти - Пользователи
Полная версия: Xterm в Tk. Почему не каждый цветной терминальный вывод отображается через Popen+communicate?
Начало » GUI » Xterm в Tk. Почему не каждый цветной терминальный вывод отображается через Popen+communicate?
1
xintrea
Имеется процесс xterm, который “вставлен” в Tk-окно:
 class Terminal(tk.Frame):
    def __init__(self, parent):
        ...
        # Получение tty с которым будет работать терминал (грубый хак)
        os.system('xterm -into %d -geometry 160x50 -sb -e "tty > /tmp/ttyinfo.txt"' % self.wid)
        fp=open('/tmp/ttyinfo.txt', 'r')
        self.tty=fp.readline().strip();
        fp.close();
        print("tty info: "+self.tty)
        # Открытие терминала с bash. Перед запуском bash выводится рабочий tty
        os.system('xterm -into '+str(self.wid)+' -geometry 160x50 -sb -e "tty ; bash -norc" &')
Выполнение команд в этом xterm-терминале сделано двумя способами:
  • Через os.system().
  • Через Popen+communicate.
Для теста я использую две команды, которые генерируют цветной вывод:
1. ip -color addr
2. ansible-playbook ourPlaybook.yml
И вот какая проблема проявилась:
  • Способ запуска через os.system() всегда работает правильно. Для обеих команд вывод в xterm цветной.
  • Способ запуска через Popen+communicate() правильно работает только для “ip -color addr”. Но для Ansible почему-то генерируется монохромный вывод.
А нужно чтобы и через Popen+communicate() правильно генерировался цветной вывод в терминал для любой команды. Потому что только этим способом можно получить stdOut + stdErr + errCode. Ведь в os.system доступен только код возврата.

Для демонстрации я сделал минимальный пример. Функции запуска выглядят так:
     # Выполнение команды в терминале - вариант 1
    def doCommand1(self, text) :
        cmdLine="(%s) <%s >%s 2> %s" % (text, self.tty, self.tty, self.tty)
        result=os.system(cmdLine)
        ...
        return result
    # Выполнение команды в терминале - вариант 2
    def doCommand2(self, text) :
        cmdLine="%s" % (text)
        resultTriada=command.run(cmdLine)
        log.echo("* Результат: "   +resultTriada[0])
        log.echo("* Вывод ошибок: "+resultTriada[1])
        log.echo("* Код возврата: "+str(resultTriada[2]))
        ...
        # Возвращается кортеж из stdOut, stdErr, errCode
        return resultTriada
Во втором случае используется метод с вызовом Popen+communicate():
 class Command():
  # Запуск внешней программы
  def run(self, cmd):
    p=Popen(cmd, stdout=PIPE, shell=True)
    stdOutData, stdErrData = p.communicate()
    errCode=p.returncode
    outData=""
    errData=""
    if not stdOutData is None :
      outData=stdOutData.decode()
    if not stdErrData is None :
      errData=stdErrData.decode()
    # Убирается последний перенос строк, чтобы в конце небыло пустой строки
    outData=re.sub("\n$", '', outData)
    errData=re.sub("\n$", '', errData)
    return(outData, errData, errCode)
В примере сделано 4 кнопки (то есть, со всеми возможными вариантами):

- IP адрес (os.system)
- IP адрес (Popen)
- Ansible (os.system)
- Ansible (Popen)

Первые три генерируют цветной вывод, а четвертая - монохромный.

Так вот, надо добиться, чтобы и вариант на 4-й кнопке, обязательно делал цветной вывод.

Ссылка на пример: https://files.fm/u/ex9nfywf2

Скриншот: https://i.ibb.co/FKZQYkt/screenshot-2023-04-25-15-45-51.png
(На нем видна часть цветного вывода 3-й кнопки, и монохромный вывод 4-й кнопки).
xintrea
В общем, проблема оказалась в Ansible. Он сам отключает цветной вывод если терминал, через который он выводит сообщения, чем-то ему не нравится. os.sytem() ему нравится, а Popen+communicate - не нравится.

Подробности; https://www.linux.org.ru/forum/development/17205600

Чтобы Ansible всегда заставить выводить цвет, можно установить переменную среды
ANSIBLE_FORCE_COLOR=True
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB