Как получить данные stdout подпроцесса асинхронно? - PullRequest
10 голосов
/ 23 января 2012

Я написал простой скрипт на python для своего приложения и предопределил некоторые быстрые команды, такие как 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 выполняется в течение длительного периода времени, но я могу видеть вывод только после полной компиляции. Как это сделать асинхронно?

Ответы [ 6 ]

12 голосов
/ 23 января 2012

Я не уверен насчет цветов, но вот как опрашивать стандартный вывод подпроцесса по одной строке за раз:

import subprocess
proc = subprocess.Popen('cmake', shell=True, stdout=subprocess.PIPE)
while proc.poll() is None:
    output = proc.stdout.readline()
    print output

Не забудьте также прочитать с stderr, так как я уверен, что cmake выдаст туда информацию.

4 голосов
/ 24 января 2012

Вы не получаете цвет, потому что cmake определяет, является ли его стандартный вывод терминалом, а если нет, то не окрашивает свой собственный вывод.Некоторые программы дают вам возможность форсировать вывод цветов.К сожалению cmake нет, так что вам не повезло.Если только вы не хотите патчить cmake самостоятельно.

Многие программы делают это, например, grep:

# grep test test.txt
test
 ^
 |
 |------- this word is red

Теперь передайте его коту:

# grep test test.txt | cat
test
 ^
 |
 |------- no longer red

grep опция --color=always для принудительной настройки цвета:

# grep test test.txt --color=always | cat
test
 ^
 |
 |------- red again
2 голосов
/ 23 января 2012

Относительно того, как получить вывод вашего процесса до его завершения, должна быть возможность сделать это, заменив:

p.stdout.read

с:

for line in p.stdout:

Что касается сохранения цветного вывода, в этом нет ничего особенного. Например, если вывод строки сохранен в файл, то в следующий раз при выполнении cat <logfile> консоль интерпретирует escape-последовательности и отобразит цвета, как и ожидалось.

1 голос
/ 22 апреля 2018

Для CMake, в частности, вы можете принудительно заставить выводить цвет, используя опцию CLICOLOR_FORCE=1:

command = 'make CLICOLOR_FORCE=1'
args = shlex.split(command)
proc = subprocess.Popen(args, stdout=subprocess.PIPE)

Затем распечатать как в принятом ответе :

while proc.poll() is None:
    output = proc.stdout.readline()
    print(output.decode('utf-8'))

Если вы декодируете в utf-8 перед печатью, вы должны увидеть цветной вывод.Если вы печатаете результат в виде байтового литерала (то есть без декодирования), вы должны увидеть escape-последовательности для различных цветов.

Попробуйте использовать опцию universal_newlines=True:

proc = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True)

Thisзаставляет вызов proc.stdout.readline() возвращать строку вместо байтового литерала, поэтому вы можете / должны пропустить вызов на decode().

0 голосов
/ 03 февраля 2013

Здесь стоит отметить использование команды 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!

0 голосов
/ 24 января 2012

Чтобы сделать асинхронный вывод, выполните что-то вроде: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

Не уверен, что вы можете захватить цветной вывод.Если вы можете получить экранированные цветовые коды, вы сможете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...