Есть ли способ захватить стандартный вывод из этого примера? - PullRequest
0 голосов
/ 15 октября 2019

Это для среды Windows.

Скомпилируйте testprocess.py (используя pyinstaller) и поместите полученный exe-файл в тестовую папку.

В той же папке запустите ptest. py.

Testprocess.py начинается и никогда не заканчивается, записывая число каждые 3 секунды в стандартный вывод.

ptest.py пытается перехватить этот вывод.

Этот код имитирует производственную проблему, которую я хотел бы решить. Подобно тому, что происходит в рабочей среде, stdout не передается в ptest.py до тех пор, пока не завершится процесс тестирования. В производственном процессе этот процесс никогда не останавливается, но он передает важный контент на стандартный вывод.

Есть ли способ для достижения этой цели?

Прикрепленный код работает нормально, пока дочерний процесс завершается.

## [testprocess.py]:

import time

x = 0

while True:
    print(x)
    time.sleep(3)
    x += 1


## [ptest.py]:

import os
import sys
import subprocess

def get_script_path():
    return os.path.dirname(os.path.realpath(sys.argv[0]))

start_dir = get_script_path()

cmd = [start_dir + os.sep + 'testprocess.exe']

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', universal_newlines=True)

print('Subprocess started.')

capture = ""

s = proc.stdout.read(1)

print('Read Stdout')

while len(s) > 0:
    sys.stdout.write(s)
    sys.stdout.flush()
    capture += s
    s = proc.stdout.read(1)
    print(s)

print(capture)

sys.exit()

Хотелось бы иметь возможность перехватить стандартный вывод дочернего процесса, пока он еще выполняется, не дожидаясь его завершения.

1 Ответ

0 голосов
/ 15 октября 2019

Это возможно, и это проще, чем вы думаете. После запуска подпроцесса вы можете непрерывно пытаться прочитать из stdout и распечатать его, если есть что напечатать. Возможно, вам придется изменить testprocess.py, чтобы очистить себя (добавив flush = True к операторам print).

p = subprocess.Popen(command, 
                     stdout = subprocess.PIPE, 
                     stderr = subprocess.STDOUT, 
                     encoding='utf-8', 
                     universal_newlines=True)

while True:
    line = p.stdout.readline()
    if line == "" and p.poll() is not None:
        break
    if line:
        print(line.strip(), flush = True)

Редактировать: Если ваша команда выглядит как python testprocess.py, вы можете пропустить необходимость добавления flush = True в операторы печати, передав вместо этого -u в качестве опции команды. -u указывает интерпретатору python работать в режиме unbuffered.

Но, я вижу, ваша команда фактически вызывает файл exe. Возможно, вам придется выяснить, как указать компилятору, как компилировать вашу программу, как unbuffered.

...