Подтвердить что ты не робот

Как получить выход из subprocess.Popen()

Я хочу, чтобы результат выполнялся Test_Pipe.py, я пробовал следующий код в Linux, но он не работал.

Test_Pipe.py

import time
while True :
    print "Someting ..."
    time.sleep(.1)

Caller.py

import subprocess as subp
import time

proc = subp.Popen(["python", "Test_Pipe.py"], stdout=subp.PIPE, stdin=subp.PIPE)

while True :
    data = proc.stdout.readline() #block / wait
    print data
    time.sleep(.1)

Строка proc.stdout.readline() заблокирована, поэтому данные не распечатываются.

4b9b3361

Ответ 1

Очевидно, вы можете использовать subprocess.communicate, но я думаю, что вы ищете вход и выход в реальном времени.

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

import subprocess
import sys

process = subprocess.Popen(
    cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)

while True:
    out = process.stdout.read(1)
    if out == '' and process.poll() != None:
        break
    if out != '':
        sys.stdout.write(out)
        sys.stdout.flush()

Ответ 2

Фрагмент Nadia действительно работает, но вызов чтения с 1-байтовым буфером крайне неоправдан. Лучший способ сделать это - установить дескриптор файла stdout для неблокирования с помощью fcntl

fcntl.fcntl(
    proc.stdout.fileno(),
    fcntl.F_SETFL,
    fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK,
)

а затем с помощью select, чтобы проверить, готовы ли данные

while proc.poll() == None:
    readx = select.select([proc.stdout.fileno()], [], [])[0]
    if readx:
        chunk = proc.stdout.read()
        print chunk

Она была права в том, что ваша проблема должна отличаться от того, что вы отправили, поскольку Caller.py и Test_Pipe.py работают, как предусмотрено.

Ответ 3

Чтобы избежать многих проблем, которые всегда могут возникать при буферизации для таких задач, как "получение выхода подпроцесса в основной процесс в реальном времени", я всегда рекомендую использовать pexpect для всех платформ, отличных от Windows, wexpect в Windows вместо subprocess, когда такие задачи желательно.

Ответ 4

Test_Pipe.py по умолчанию отключает свой stdout, поэтому proc в Caller.py не видит никакого вывода, пока дочерний буфер не будет заполнен (если размер буфера составляет 8 КБ, то для заполнения Test_Pipe.py stdout требуется около минуты буфер).

Чтобы сделать вывод небуферизованным (с буферизацией строки для текстовых потоков), вы можете передать -u флаг дочернему Python script, Он позволяет считывать выходные данные подпроцесса "в режиме реального времени":

import sys
from subprocess import Popen, PIPE

proc = Popen([sys.executable, "-u", "Test_Pipe.py"], stdout=PIPE, bufsize=1)
for line in iter(proc.stdout.readline, b''):
    print line,
proc.communicate()

Смотрите ссылки в Python: прочитайте потоковый ввод из subprocess.communicate() о том, как решить проблему блочного буферизации для дочерних процессов, отличных от Python.