Как получить выход из 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()
заблокирована, поэтому данные не распечатываются.
Ответы
Ответ 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.