Обтекание подпроцессом 'stdout / stderr

Я хотел бы как захватить, так и отобразить вывод процесса, который я вызываю через подпроцесс Python.

Я думал, что могу просто передать свой файл-подобный объект как именованный параметр stdout и stderr

Я вижу, что он обращается к fileno поэтому он что-то делает с объектом. Однако метод write() никогда не вызывается. Мой подход полностью отключен, или я просто что-то упустил?

 class Process(object): class StreamWrapper(object): def __init__(self, stream): self._stream = stream self._buffer = [] def _print(self, msg): print repr(self), msg def __getattr__(self, name): if not name in ['fileno']: self._print("# Redirecting: %s" % name) return getattr(self._stream, name) def write(self, data): print "###########" self._buffer.append(data) self._stream.write(data) self._stream.flush() def getBuffer(self): return self._buffer[:] def __init__(self, *args, **kwargs): print ">> Running `%s`" % " ".join(args[0]) self._stdout = self.StreamWrapper(sys.stdout) self._stderr = self.StreamWrapper(sys.stderr) kwargs.setdefault('stdout', self._stdout) kwargs.setdefault('stderr', self._stderr) self._process = subprocess.Popen(*args, **kwargs) self._process.communicate() 

Обновить:

Что-то, что я хотел бы работать, – это управляющие символы ANSI, чтобы переместить курсор и переопределить предыдущий материал вывода. Я не знаю, является ли это правильным термином, но вот пример того, что я имел в виду: я пытаюсь автоматизировать некоторые вещи GIT, и там у них есть прогресс, который обновляется без записи в новую строку каждый раз.

Обновление 2

Мне важно, что вывод подпроцесса отображается сразу же. Я попытался использовать subprocess.PIPE для захвата вывода и отображения его вручную, но я смог получить его, чтобы отобразить вывод, как только процесс завершился. Тем не менее, я хотел бы видеть вывод в режиме реального времени.

    Stdin, stdout и stderr процесса должны быть реальными файловыми дескрипторами. (На самом деле это не ограничение, налагаемое Python, а скорее то, как работают трубы на уровне ОС.) Таким образом, вам понадобится другое решение.

    Если вы хотите отслеживать оба stdout stderr в режиме реального времени, вам понадобятся асинхронные операции ввода-вывода или потоки.

    • Асинхронный ввод-вывод: со стандартным синхронным (= блокирующим) вводом-выводом считывание одного из потоков может блокировать, запрещая доступ к другому в режиме реального времени. Если вы работаете в Unix, вы можете использовать неблокирующий ввод-вывод, как описано в этом ответе . Однако в Windows вам не повезет с этим подходом. Подробнее об асинхронном вводе-выводе в Python и некоторых альтернативах показано в этом видео .

    • Темы: Еще один распространенный способ решения этой проблемы – создать один поток для каждого дескриптора файла, который вы хотите прочитать в режиме реального времени. Потоки обрабатывают только дескриптор файла, к которому они относятся, поэтому блокирование ввода-вывода не повредит.

    Посмотрите здесь .

     p = subprocess.Popen(cmd, shell=True, bufsize=64, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 

    Файл не подходит достаточно близко. Это должен быть фактический файл с фактическим дескриптором файла. Используйте поддержку subprocess для труб и, при необходимости, прочитайте их.

    Есть ли причина, по которой у вас есть класс внутри класса? И stdout и stderr могут взять любой файл, например, например, попробовать. Поэтому просто передать открытый тип файла или stringIO должно быть достаточно, чтобы изменить поток

     import sys sys.stdout = open('test.txt','w') print "Testing!" sys.stdout.write('\nhehehe') sys.stdout = sys.__stdout__ sys.exit(0)