Получение stdout для отображения вызываемого скрипта, содержащего ввод - PullRequest
4 голосов
/ 30 марта 2012

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

print ("Line 1 of Text")
variable = raw_input("Input 1 :")
print "Line 2 of Text Input: ", vairable

Часть кода, который я запускаю, -

import subprocess

cmd='testfile.py'
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
so, se = p.communicate()
print(so)

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

Спасибо

Ответы [ 2 ]

3 голосов
/ 30 марта 2012

Здесь есть две проблемы.

  1. Во-первых, python буферизует вывод в stdout, и вам нужно это предотвратить.Вы можете вставить вызов на sys.stdout.flush() в testfile.py, как предложил Илия Френкель, или вы можете использовать python -u для выполнения testfile.py с небуферизованным вводом / выводом.(См. другой вопрос о переполнении стека , с которым связал Илия.)

  2. Вам нужен способ асинхронного чтения данных из подпроцесса и затем, когда онготов к вводу, распечатав прочитанные вами данные, чтобы появилось приглашение для пользователя.Для этого было бы очень полезно иметь асинхронную версию модуля подпроцесса .

Я загрузил асинхронный подпроцесс и переписал ваш скрипт для его использования, наряду с использованием python -u для получения небуферизованного ввода-вывода:

import async_subprocess as subprocess

cmd = ['python', '-u', 'testfile.py']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
so = p.asyncread()
print so,
(so, se) = p.communicate()
print so

КогдаЯ запускаю этот скрипт, используя python -u, я получаю следующие результаты:

$ python -u script.py
Line 1 of Text
Input 1:

и скрипт останавливается, ожидая ввода.Это желаемый результат.

Если я потом что-то наберу (например, «Привет»), я получу следующее:

$ python -u script.py
Line 1 of Text
Input 1:Hullo
 Line 2 of Text Input:  Hullo
1 голос
/ 30 марта 2012

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

Но в любом случае, это не то, что вы спросили.

Я на самом деле получил это из другого вопроса stackoverflow:

import subprocess, sys
cmd='testfile.py' 
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
while True: 
    out = p.stdout.read(20) 
    if out == '' and p.poll() != None: 
        break 
    if out != '': 
        sys.stdout.write(out) 
        sys.stdout.flush()

Во-первых, он открывает ваш процесс: затем он постоянно читает вывод из p и печатает его на экране, используя sys.stdout.write. Часть, которая заставляет все это работать, - sys.stdout.flush(), которая будет постоянно «очищать» вывод программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...