Python: Как прочитать стандартный вывод без блокировки из другого процесса? - PullRequest
12 голосов
/ 20 июня 2011

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

Вот фрагмент того, что я пытаюсь сделать. (Первая часть - это просто скрипт на python, который что-то пишет в стандартный вывод.)

import subprocess

p = subprocess.Popen('python -c \'\
from time import sleep\n\
for i in range(3):\n\
    sleep(1)\n\
    print "Hello", i\
\'', shell = True, stdout = subprocess.PIPE)

while p.poll() == None:
    #read the stdout continuously
    pass

print "Done"

Я знаю, что существует множество вопросов, посвященных одной и той же теме. Однако ни один из найденных мной не смог ответить на мой вопрос.

Ответы [ 3 ]

12 голосов
/ 20 июня 2011

То, что происходит, является буферизацией на стороне писателя.Поскольку вы пишете такие маленькие фрагменты из небольшого фрагмента кода, базовый объект FILE буферизует вывод до конца.Следующее работает так, как вы ожидаете.

#!/usr/bin/python

import sys
import subprocess

p = subprocess.Popen("""python -c '
from time import sleep ; import sys
for i in range(3):
    sleep(1)
    print "Hello", i
    sys.stdout.flush()
'""", shell = True, stdout = subprocess.PIPE)

while True:
    inline = p.stdout.readline()
    if not inline:
        break
    sys.stdout.write(inline)
    sys.stdout.flush()

print "Done"

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

5 голосов
/ 20 июня 2011

следующий код будет выводить stdout построчно, пока подпроцесс работает, пока метод readline () не вернет пустую строку:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, ''):
    print line
p.stdout.close()
print 'Done'

обновление, относящееся к вашему вопросу лучше:

import subprocess

p = subprocess.Popen(['python'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write("""
from time import sleep ; import sys
for i in range(3):
    sleep(1)
    print "Hello", i
    sys.stdout.flush()
""")
p.stdin.close()
for line in iter(p.stdout.readline, ''):
    print line
p.stdout.close()
print 'Done'
0 голосов
/ 20 июня 2011

Вы можете использовать subprocess.communicate(), чтобы получить вывод из stdout. Что-то вроде:

while(p.poll() == None):
    #read the stdout continuously
    print(p.communicate()[0])
    pass

Более подробная информация доступна по адресу: http://docs.python.org/library/subprocess.html

...