Как я могу распечатать и отобразить вывод stdout и stderr подпроцесса без искажений?

Может быть, есть кто-то в эфире, который может помочь мне с этим. ( Я встречал несколько подобных вопросов в SO, но ни один из них не касается как стандартных ошибок, так и стандартных ошибок, и не имеет дело с ситуацией, очень похожей на мою, отсюда и этот новый вопрос.)

У меня есть функция python, которая открывает подпроцесс , ожидает его завершения, а затем выводит код возврата, а также содержимое стандартных каналов вывода и стандартных каналов ошибок. Пока процесс выполняется, я хотел бы также отображать вывод обоих каналов по мере их заполнения. Моя первая попытка привела к примерно следующему:

process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout = str()
stderr = str()
returnCode = None
while True:
    # collect return code and pipe info
    stdoutPiece = process.stdout.read()
    stdout = stdout + stdoutPiece
    stderrPiece = process.stderr.read()
    stderr = stderr + stderrPiece
    returnCode = process.poll()

    # check for the end of pipes and return code
    if stdoutPiece == '' and stderrPiece == '' and returnCode != None:
        return returnCode, stdout, stderr

    if stdoutPiece != '': print(stdoutPiece)
    if stderrPiece != '': print(stderrPiece)

Однако с этим есть пара проблем. Поскольку read () читает до EOF , первой строки while цикл не вернется, пока подпроцесс не закроет канал.

Я мог бы заменить read () в пользу read (int) , но вывод на печать искажается, обрезается в конце прочитанных символов. Я мог бы readline () в качестве замены, но распечатанный вывод искажается из-за чередования строк вывода и ошибок, когда одновременно возникает много и того, и другого.

Возможно, есть вариант read-until-end-of-buffer () , о котором я не знаю? Или, может быть, это можно реализовать?

Может быть, лучше всего реализовать оболочку sys.stdout , как предлагается в этом ответе на другой пост ? Однако я бы хотел использовать только оболочку в этой функции.

Есть ли другие идеи от сообщества?

Я благодарен за помощь! :)

РЕДАКТИРОВАТЬ : Решение действительно должно быть кроссплатформенным, но если у вас есть идеи, которых нет, пожалуйста, поделитесь ими, чтобы продолжить мозговой штурм.


Что касается еще одного из моих собеседников о подпроцессах python, взгляните на еще один из моих вопросов о учета накладных расходов подпроцесса во времени .

8
задан Community 23 May 2017 в 11:55
поделиться