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

У меня возникают проблемы с перенаправлением stdio другой программы с использованием модуля subprocess. Просто чтение из 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

Ответы

Ответ 1

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

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

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

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

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

В этом месте я хотел показать вам новую документацию Python 2.6, но она не объясняет проблему с флешем:( О, хорошо...