Как правильно взаимодействовать с процессом с помощью модуля подпроцесса

У меня проблемы с перенаправлением stdio другой программы с помощью модуля подпроцесса. Простое чтение из stdout приводит к зависанию, и Popen.communicate () работает, но закрывает каналы после чтения / записи. Как проще всего это реализовать?

Я играл с этим в окнах:

import subprocess
proc = subprocess.Popen('python -c "while True: print \'Hi %s!\' % raw_input()"',
                        shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                        stderr=subprocess.STDOUT)
while True:
    proc.stdin.write('world\n')
    proc_read = proc.stdout.readline()
    if proc_read:
        print proc_read

person Ivan Baldin    schedule 14.01.2009    source источник
comment
Дубликат: stackoverflow.com/questions/163542/, stackoverflow.com/questions/295459/   -  person S.Lott    schedule 14.01.2009
comment
-u флаг решит эту проблему для подпроцесса Python. Также существуют модули pexpect, pty и _ 4_, stdbuf, script, которые могут помочь решить проблему с буферизацией блоков.   -  person jfs    schedule 22.05.2013


Ответы (1)


Не соответствует вашему примеру на 100%, но помогает понять основную проблему: процесс P запускает дочерний элемент C. Ребенок C записывает что-то в свой стандартный вывод. stdout C - это канал с буфером на 4096 символов, а вывод короче этого значения. Теперь C ждет ввода. Для C все нормально.

P ожидает вывода, который никогда не придет, потому что ОС не видит причин очищать выходной буфер C (с таким небольшим количеством данных в нем). Поскольку P никогда не получает вывод C, он никогда ничего не записывает в C, поэтому C зависает, ожидая ввода от P.

Исправление: используйте сброс после каждой записи в канал, заставляя ОС отправлять данные сейчас.

В вашем случае добавление proc.stdin.flush() в основной цикл while и sys.stdout.flush() в дочерний цикл после печати должно решить вашу проблему.

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

Здесь я хотел показать вам новую документацию по Python 2.6, но она также не объясняет проблему с промывкой :( Ну что ж ...

person Aaron Digulla    schedule 14.01.2009
comment
Хорошее объяснение. Еще из pexpect docs: В: Почему бы просто не использовать труба (popen ())? - person jfs; 22.05.2013
comment
Документы Pexpect перемещены: вот новая ссылка - person jfs; 13.09.2016