Перехват stdout в реальном времени из другого процесса в Python

Я хотел бы запустить системный процесс, перехватить вывод и изменить его в режиме реального времени, построчно, в скрипте Python.

Моя лучшая попытка, которая ожидает завершения процесса перед печатью:

#!/usr/bin/env python
import subprocess

cmd = "waitsome.py"
proc = subprocess.Popen(cmd, shell=True, bufsize=256, stdout=subprocess.PIPE)
for line in proc.stdout:
    print ">>> " + line.rstrip()

Сценарийwaitsome.py просто печатает строку каждые полсекунды:

#!/usr/bin/env python
import time
from sys import stdout

print "Starting"
for i in range(0,20):
    time.sleep(0.5)
    print "Hello, iteration", i
    stdout.flush()

Есть ли простое решение, чтобы получитьsubprocess разрешить перебор выходных данных в режиме реального времени? Должен ли я использовать темы?

Когда-то я писал на Perl, и это было очень просто:

open(CMD, "waitsome.py |");
while (<CMD>) {
    print ">>> $_";
}
close(CMD);
 Seth Johnson06 июл. 2009 г., 04:13
Извините, я только увидел первый и понял, что это проблема сsubprocess' буферизация, а не родительского сценария Python.

Ответы на вопрос(2)

Все это может быть заключено в итератор как:

def subprocess_readlines(out):
    while True:
        line = out.readline()
        if not line:
            return
        yield line

И называется как:

for line in proc.stdout:
    print ">>>", line.rstrip()
 Seth Johnson25 февр. 2018 г., 02:07
Буферизация в Python сильно изменилась с тех пор, как я написал оригинальный вопрос :) Да, то, что потребовало много усилий для Python 2.5, теперь можно выполнить в несколько строк.
Решение Вопроса

Зацикливание на файле неизбежно буферизует вещи большими порциями - известная проблема во всех реализациях Python 2. *. Это работает так, как вы намереваетесь в Python 3.1, с последним циклом, который немного отличается:

for line in proc.stdout:
    print(">>> " + str(line.rstrip()))

Если обновление до Python 3.1 нецелесообразно (и я знаю, что это будет часто!), Идите другим путем и напишите цикл старомодным способом - следующая версия цикла работает так, как вы собираетесь в Python 2. * :

while True:
    line = proc.stdout.readline()
    if not line:
        break
    print ">>> " + line.rstrip()
 06 июл. 2009 г., 04:16
Да, но теперь, когда вышел Python 3.1 (с намного лучшей реализацией всего стека ввода / вывода), нет никаких причин придерживаться версии 3.0 (это была определенно переходная версия ;-).
 06 июл. 2009 г., 03:55
Это также работает в Python 3.0
 21 дек. 2013 г., 06:56
for line in iter(proc.stdout.readline, ''): print ">>>", line, может использоваться вместо цикла while в Python 2.

Ваш ответ на вопрос