Interactúa con una aplicación de consola de Windows a través de Python

Estoy usando python 2.5 en Windows. Deseo interactuar con un proceso de consola a través de Popen. Actualmente tengo este pequeño fragmento de código:

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() 

Puedo escribir en stdin pero no puedo leer desde stdout. ¿Me he perdido un paso? No quiero usar p.communicate (“command”) [0] ya que finaliza el proceso y necesito interactuar con el proceso de forma dinámica a lo largo del tiempo.

Gracias por adelantado.

Su problema aquí es que está intentando controlar una aplicación interactiva.

stdout.read() continuará leyendo hasta que haya llegado al final de la secuencia, el archivo o la tubería. Desafortunadamente, en el caso de un progtwig interactivo, la tubería solo se cierra cuando el progtwig sale; lo que nunca es, si el comando que envió no fue "quit" .

Deberá volver a leer la salida del subproceso línea por línea utilizando stdout.readline() , y es mejor que tenga una manera de saber cuándo el progtwig está listo para aceptar un comando y cuándo el comando que emitió. El progtwig está terminado y puede suministrar uno nuevo. En el caso de un progtwig como cmd.exe , incluso readline() no será suficiente, ya que la línea que indica que se puede enviar un nuevo comando no termina con una nueva línea, por lo que tendrá que analizar el byte por byte de salida. Aquí hay una secuencia de comandos de muestra que ejecuta cmd.exe , busca el aviso, luego emite un dir y luego una exit :

 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 

Si el tiempo no es importante y la interactividad para un usuario no es necesaria, puede ser mucho más simple solo agrupar las llamadas:

 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() 

¿Has intentado forzar las líneas de las ventanas? es decir

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

ACTUALIZAR:

Acabo de comprobar la solución en windows cmd.exe y funciona con readline (). Pero tiene un problema: los bloques stdout.readline de Popen. Por lo tanto, si la aplicación alguna vez devuelve algo sin una línea de finalización, su aplicación quedará atascada para siempre.

Pero hay una solución para ese cheque: http://code.activestate.com/recipes/440554/

Creo que deberías intentar usar readline () en su lugar?

Edición: lo siento, malinterpretar.

Tal vez esta pregunta te pueda ayudar?

¿Es posible que la aplicación de la consola esté almacenando en búfer su salida de alguna manera para que solo se envíe a la salida estándar cuando la canalización está cerrada? Si tiene acceso al código de la aplicación de la consola, ¿quizás podría ser útil pegar un color después de un lote de datos de salida?

Alternativamente, ¿en realidad está escribiendo en stderr y en lugar de stdout por alguna razón?

Solo miré su código otra vez y pensé en otra cosa, veo que está enviando el “comando \ n”. ¿Podría la aplicación de la consola simplemente estar esperando un carácter de retorno de carro en lugar de una nueva línea? Tal vez la aplicación de la consola está esperando a que envíe el comando antes de que produzca resultados.

Tenía exactamente el mismo problema aquí. Busqué en el código fuente de DrPython y robé la solución wx.Execute () , que funciona bien, especialmente si su script ya está usando wx. Aunque nunca encontré la solución correcta en la plataforma de Windows …