Как правильно взаимодействовать с процессом с помощью модуля подпроцесса - PullRequest
10 голосов
/ 14 января 2009

У меня проблемы с перенаправлением 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

1 Ответ

17 голосов
/ 14 января 2009

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

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

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

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

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

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

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