Как получить асинхронные данные stdout подпроцесса?
Я написал простой python script для своего приложения и предопределл некоторые быстрые команды, например make и т.д.
Я написал функцию для запуска системных команд (linux):
def runCommand(commandLine):
print('############## Running command: ' + commandLine)
p = subprocess.Popen(commandLine, shell = True, stdout = subprocess.PIPE)
print (p.stdout.read().decode('utf-8'))
Все работает хорошо, за исключением нескольких вещей:
-
Я использую cmake, и его вывод окрашен. Есть ли шансы сохранить цвета на выходе?
-
Я могу посмотреть результат после завершения процесса. Например, make запускается в течение длительного периода времени, но я могу видеть вывод только после полной компиляции. Как сделать это асинхронно?
Ответы
Ответ 1
Я не уверен в цветах, но здесь, как опросить подпроцесс stdout по одной строке за раз:
import subprocess
proc = subprocess.Popen('cmake', shell=True, stdout=subprocess.PIPE)
while proc.poll() is None:
output = proc.stdout.readline()
print output
Не забудьте также прочитать из stderr, так как я уверен, что cmake выдаст там информацию.
Ответ 2
Вы не получаете цвет, потому что cmake
обнаруживает, является ли его stdout терминалом, если он не цвет его собственного вывода. Некоторые программы дают вам возможность форматировать вывод цветов. К сожалению, cmake
нет, так что вам там не повезло. Если вы не хотите исправлять cmake
самостоятельно.
Это много программ, например grep:
# grep test test.txt
test
^
|
|------- this word is red
Теперь перетащите его в cat:
# grep test test.txt | cat
test
^
|
|------- no longer red
grep
параметр --color=always
, чтобы заставить цвет:
# grep test test.txt --color=always | cat
test
^
|
|------- red again
Ответ 3
Относительно того, как получить результат вашего процесса до его завершения, должно быть возможно сделать это, заменив:
p.stdout.read
с:
for line in p.stdout:
Что касается сохранения цветного вывода, в этом нет ничего особенного. Например, если вывод строки сохраняется в файл, то в следующий раз выполняется cat <logfile>
, консоль будет интерпретировать escape-последовательности и отображать цвета, как ожидалось.
Ответ 4
Для вывода async выполните следующее: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554
Не уверен, что вы можете захватить цветной выход. Если вы можете получить экранированные цветовые коды, вы можете это сделать.
Ответ 5
Здесь стоит упомянуть использование команды script
в качестве псевдотерминала и быть обнаруженным как дескриптор файла tty вместо дескриптора перенаправления (pipe), см.
bash команда сохранить цвет при конвейерах
Работает как шарм...
В соответствии с примером в вопросе просто давайте script
выполнить cmake
:
import subprocess
proc = subprocess.Popen('script cmake', shell=True, stdout=subprocess.PIPE)
while proc.poll() is None:
output = proc.stdout.readline()
print output
Это трюки cmake
, считая, что он выполняется с терминала, и вы получите конфету ANSI, которую вы после.
NJoy!