@oleg_botanik

Как получить текущий вывод подчиненного процесса?

Ниже под "подчиненным процессом" понимаю процесс, запущенный из кода текущего.
Мне бы хотелось в коде своего приложения иметь возможность запускать другие процессы и отслеживать их работу.
Т.е. например:
мое приложение запускает подчиненное (gunicorn) (который остается висеть)
мое приложение ждет пока подчиненное выведет ("...Booting worker with pid:...")
мое приложение делает запросы и если есть новый вывод подчиненного - получает его

Если делать так:
os.system('gunicorn...')
то вывод выходит в вывод моего приложения и я не знаю как его можно отделить, хотя в этом варианте удачно то, что мое приложение не ждет окончания подчиненного
Если делать так:
p = subprocess.Popen('gunicorn...', stdout=subprocess.PIPE...

то для получения вывода необходимо дождаться завершения процесса, что совсем не подходит в моем случае (вывод в файл также осуществляется по окончании процесса)
Подскажите, какие инструменты python используются для получения текущего вывода подчиненного процесса до его завершения.
Спасибо.
  • Вопрос задан
  • 495 просмотров
Пригласить эксперта
Ответы на вопрос 2
sanya84
@sanya84
Фанатик Python 3
Так?
from subprocess import Popen, PIPE, DEVNULL, STDOUT
from time import sleep

list_argumrnts = ['ping', 'www.google.com']
with Popen(list_argumrnts, stdout=PIPE, stdin=DEVNULL, stderr=STDOUT, encoding='cp866') as process:
	for line in iter(process.stdout.readline, b''):
		sleep(0.1)
		print(line.rstrip('\n'))
		if line == '':
			break
Ответ написан
Комментировать
exibite777
@exibite777
Ведущий системный аналитик
Пример №1. Предположим у нас есть родительский процесс parent.py, child.py и файл test.txt. На вход child.py будем отдавать файл, выход будем читать командой child.stdout.read()
модуль parent.py
from subprocess import Popen
import subprocess as sp

with open("test.txt", "r") as file:
    child=Popen(['python', 'child.py'], stdin=file, stdout=sp.PIPE)
    s=' '
    while s:
        s=child.stdout.read()
        print (s.rstrip().decode(errors='ignore'))
модуль child.py
print(input(), '- all is good')
time.sleep(1)
print(input(), '- all is good')
time.sleep(1)
print(input(), '- all is good')
time.sleep(1)
файл test.txt
hello1
hello2
hello3

Результат, который будет получен через три секунды
hello1 - all is good
hello2 - all is good
hello3 - all is good

Дочерний процесс не выбрасывает кадую строку на вывод. Вывод становится доступным по завершению работы дочернего процесса. Родительский процесс читает вывод командой child.stdout.read().

Пример №2. Если необходимо своевременно отлавливать вывод дочернего процесса, то нужно в него добавить инструкцию sys.stdout.flush(), а в родительском заменить child.stdout.read() на child.stdout.readline()
модуль parent.py
from subprocess import Popen
import subprocess as sp

with open("test.txt", "r") as file:
    child=Popen(['python', 'child.py'], stdin=file, stdout=sp.PIPE)
    s=' '
    while s:
        s=child.stdout.readline()
        print (s.rstrip().decode(errors='ignore'))
модуль child.py
print(input(), '- all is good')
time.sleep(1); sys.stdout.flush()	
print(input(), '- all is good')
time.sleep(1); sys.stdout.flush()	
print(input(), '- all is good')
time.sleep(1); sys.stdout.flush()


Предвосхищая комментарий: если дочерняя программа не ваша или она вообще не на python, то инструкции sys.stdout.flush() может не быть. Поэтому вывод будет доступен только по завершению дочернего процесса. В таком случае замена инструкции child.stdout.read() на child.stdout.readline() в родительском процессе ничего не даст, цикл в коде позволит вам прочитать построчно весь вывод. Но по времени этот вывод, естественно, будет не синхронизирован с тем, когда эти строки генерировал дочерний процесс
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы