Имеется процесс 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-й кнопки).