Взаимодействие с консольным приложением Windows через Python

Я использую python 2.5 для Windows. Я хочу взаимодействовать с консольным процессом через Popen. В настоящее время у меня есть этот небольшой фрагмент кода:

p = Popen( ["console_app.exe"], stdin=PIPE, stdout=PIPE ) # issue command 1... p.stdin.write( 'command1\n' ) result1 = p.stdout.read() # <---- we never return here # issue command 2... p.stdin.write( 'command2\n' ) result2 = p.stdout.read() 

Я могу написать stdin, но не могу читать из stdout. Я пропустил шаг? Я не хочу использовать p.communicate («command») [0], поскольку он завершает процесс, и мне нужно динамически взаимодействовать с процессом со временем.

Заранее спасибо.

Ваша проблема заключается в том, что вы пытаетесь контролировать интерактивное приложение.

stdout.read() будет продолжать чтение до тех пор, пока не достигнет конца потока, файла или трубы. К сожалению, в случае интерактивной программы труба закрывается только тогда, когда программа выйдет; которое никогда не было, если команда, которую вы отправили, была чем-то другим, кроме "quit" .

Вам нужно будет вернуться к чтению вывода подпроцесса по stdout.readline() с помощью stdout.readline() , и вам лучше будет узнать, когда программа готова принять команду, и когда вы выдали команду программа завершена, и вы можете поставить новую. В случае такой программы, как cmd.exe , даже readline() не будет достаточным, так как строка, которая указывает, что новая команда может быть отправлена, не прерывается новой строкой, поэтому придется анализировать выходные байты. Вот пример скрипта, который запускает cmd.exe , ищет приглашение, а затем выдает dir а затем выходит:

 from subprocess import * import re class InteractiveCommand: def __init__(self, process, prompt): self.process = process self.prompt = prompt self.output = "" self.wait_for_prompt() def wait_for_prompt(self): while not self.prompt.search(self.output): c = self.process.stdout.read(1) if c == "": break self.output += c # Now we're at a prompt; clear the output buffer and return its contents tmp = self.output self.output = "" return tmp def command(self, command): self.process.stdin.write(command + "\n") return self.wait_for_prompt() p = Popen( ["cmd.exe"], stdin=PIPE, stdout=PIPE ) prompt = re.compile(r"^C:\\.*>", re.M) cmd = InteractiveCommand(p, prompt) listing = cmd.command("dir") cmd.command("exit") print listing 

Если синхронизация не важна, и интерактивность для пользователя не требуется, это может быть намного проще, просто для пакетных вызовов:

 from subprocess import * p = Popen( ["cmd.exe"], stdin=PIPE, stdout=PIPE ) p.stdin.write("dir\n") p.stdin.write("exit\n") print p.stdout.read() 

Вы пытались заставить оконные линии? т.е.

 p.stdin.write( 'command1 \r\n' ) p.stdout.readline() 

ОБНОВИТЬ:

Я только что проверил решение на windows cmd.exe и работает с readline (). Но у него есть одна проблема с файлами stdout.readline. Поэтому, если приложение когда-либо вернет что-то без конца, ваше приложение застрянет навсегда.

Но для этого есть работа: http://code.activestate.com/recipes/440554/

Я думаю, вы могли бы попытаться использовать readline () вместо этого?

Редактировать: извините, неправильно понял.

Может быть, этот вопрос может вам помочь?

Возможно ли, что консольное приложение каким-то образом буферизует свой вывод, так что оно отправляется только на stdout, когда труба закрыта? Если у вас есть доступ к коду для консольного приложения, возможно, приклейте флеш после того, как может помочь партия выходных данных?

Альтернативно, это на самом деле запись в stderr и вместо stdout по какой-то причине?

Просто посмотрел на ваш код и подумал о чем-то другом, я вижу, что вы отправляете команду «\ n». Может ли консольное приложение просто ждать символа возврата каретки вместо новой строки? Возможно, консольное приложение ждет вас, чтобы отправить команду, прежде чем она выведет какой-либо вывод.

Здесь была такая же проблема. Я выкопал исходный код DrPython и украл решение wx.Execute () , которое отлично работает, особенно если ваш скрипт уже использует wx. Я никогда не нашел правильного решения на платформе Windows, хотя …