Подпроцесс Python: открыть stdin, мешающий stdout / stderr

Очень этим озадачен. При использовании Popen, если используется только stdout или stderr, работает следующий код:

def run(self):
    self.externalProcess = subprocess.Popen(['./external_process.out 1>&2'], shell=True, stderr=subprocess.PIPE)
    while self.externalBinary.poll() is None:
        print('Still running')
    print('Done running')

Я использую дескриптор файла stderr, потому что я отслеживаю вывод процесса в реальном времени в графическом интерфейсе пользователя, а stderr не буферизуется. См. Другой мой вопрос для получения дополнительной информации об этом беспорядке: Python захватывает стандартный вывод из подпроцесса построчно

Проблема, с которой я столкнулся, заключается в том, что как только я добавляю stdin, чтобы разрешить передачу пользовательского ввода внешнему процессу, он начинает действовать так, как будто stdout снова буферизуется:

def run(self):
    self.externalProcess = subprocess.Popen(['./external_process.out 1>&2'], shell=True, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    while self.externalBinary.poll() is None:
        print('Still running')
    print('Done running')

У меня вопрос: почему stdin влияет на stdout и stderr?


person anderspitman    schedule 03.10.2011    source источник
comment
Каковы симптомы вашей проблемы? Что-то заблокировано, чего не должно быть?   -  person jwd    schedule 03.10.2011
comment
Также приветствуется рабочий код - ваши примеры работают не так, как написано. Что такое stdout=STDERR, например?   -  person jwd    schedule 03.10.2011
comment
Да, я заметил, что не существует такой вещи, как subprocess.STDERR. Должен быть исправлен сейчас. Симптомы заключаются в том, что у меня есть текстовое поле в моем приложении wxPython, которое выводит результат построчно. Когда я добавляю аргумент stdin, он отображает только несколько строк, которые останавливаются. Когда я его удаляю, он продолжает отображать вывод моего внешнего процесса, который является программой C.   -  person anderspitman    schedule 03.10.2011
comment
Куда вы на самом деле отправляете входные данные дочернему процессу? Я не вижу этого в вашем втором примере ...   -  person jwd    schedule 03.10.2011
comment
Я не включил это, потому что я вижу проблему, как только добавляю аргумент. Мне даже не нужно пытаться использовать стандартный ввод. После прочтения ссылки ниже я думаю, что моя проблема в том, что я захожу в тупик из-за кеширования, поэтому я работаю над тем, чтобы обойти это. Мне не нужно использовать stdin, пока я не закрою дочерний процесс (я просто отправляю новую строку, чтобы имитировать нажатие клавиши ввода, и именно так эта программа завершается чисто).   -  person anderspitman    schedule 04.10.2011


Ответы (1)


Похоже, вы пытаетесь записать данные в подпроцесс (через STDIN), а также прочитать его вывод (через STDOUT) в интерактивном режиме.

Как упоминалось в ответе на этот вопрос SO, это нет-нет!

Вы можете использовать Popen.communicate, но это блокирующий вызов, который будет ждать завершения всех коммуникаций (вы не можете опрашивать, как в своем примере)

person jwd    schedule 03.10.2011
comment
Хорошая ссылка. Раньше я не разбирался в проблеме блокировки. Я пытаюсь наладить общение, но это не так далеко. См. Мой комментарий выше. - person anderspitman; 04.10.2011
comment
@ tanders12: Какие у тебя проблемы с communicate()? - person jwd; 04.10.2011
comment
Общение (), кажется, буферизует все, пока дочерний элемент не выйдет. Мне нужна строка с буферизацией или без буферизации. Я пытаюсь этого добиться, не меняя код у ребенка. Прямо сейчас я пытаюсь заставить Pexpect работать, и это выглядит многообещающим. - person anderspitman; 04.10.2011