2012-01-23 14 views
10

me escribió un simple script en Python para mi aplicación y algunos comandos predefinidos rápida como hacer etc.¿Cómo obtener los subprocesos 'stdout data asincrónicamente?

He escrito una función para ejecutar comandos del sistema (Linux):

def runCommand(commandLine): 
    print('############## Running command: ' + commandLine) 
    p = subprocess.Popen(commandLine, shell = True, stdout = subprocess.PIPE) 
    print (p.stdout.read().decode('utf-8')) 

todo funciona bien, excepto una algunas cosas:

  • estoy usando cmake y es es de color de salida. ¿Alguna posibilidad de guardar colores en la salida?

  • Puedo ver la salida después de que el proceso haya finalizado. Por ejemplo, hace que se ejecute durante un largo período de tiempo, pero puedo ver la salida solo después de la compilación completa. ¿Cómo hacerlo asincrónicamente?

Respuesta

12

no estoy seguro acerca de los colores, pero aquí es como para sondear la salida estándar una línea del subproceso a la vez:

import subprocess 
proc = subprocess.Popen('cmake', shell=True, stdout=subprocess.PIPE) 
while proc.poll() is None: 
    output = proc.stdout.readline() 
    print output 

No se olvide de leer de stderr, así, como estoy seguro de cmake emitirá información allí.

+0

Bien, gracias. Funciona. – Ockonal

2

cuanto a cómo conseguir la salida de su proceso antes de que finalice, debería ser posible hacer que la sustitución:

p.stdout.read 

con:

for line in p.stdout: 

cuanto a cómo ahorrar coloreado salida, no hay nada especial sobre eso. Por ejemplo, si la salida de la fila se guarda en un archivo, la próxima vez que se ejecute cat <logfile>, la consola interpretará las secuencias de escape y mostrará los colores como se esperaba.

+0

con 'readline()' Tengo números en fila en lugar de texto, ¿qué ocurre? – Ockonal

+1

@Ockonal En realidad, si usa el bucle for, no es necesario usar 'readline'. Puede encontrar un ejemplo de ambas estrategias [aquí] (http://stackoverflow.com/q/2804543/183066). – jcollado

+0

En realidad 'para la línea en p.stdout' no es bueno en Python 2 de acuerdo con http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line#comment11236752_2813530 –

0

Para hacer la salida asíncrona hacer algo como: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

No estoy seguro si se puede capturar la salida de color. Si puede obtener los códigos de color escapados, puede hacerlo.

+0

Si obtenemos los códigos de color, el terminal los traducirá. Sin embargo, el problema es que la mayoría de las aplicaciones distinguen entre estar conectado a un terminal o conectarse a otra aplicación. La única forma de convencer a estas aplicaciones para que sigan produciendo los códigos de color es falsificando que la aplicación receptora (en este caso, nuestro proceso python) es de hecho una tty y no una tubería. Una tarea mucho más fácil decirlo que hacerlo ... –

4

No obtiene el color porque cmake detecta si su stdout es un terminal, si no es así, no colorea su propia salida. Algunos programas le dan la opción de forzar la salida de color. Lamentablemente, cmake no, por lo que no tiene suerte allí. A menos que quiera parchear cmake usted mismo.

Muchos de los programas hacen esto, por ejemplo grep:

# grep test test.txt 
test 
^ 
| 
|------- this word is red 

Ahora tubería que al gato:

# grep test test.txt | cat 
test 
^ 
| 
|------- no longer red 

grep opción --color=always a la fuerza de los colores:

# grep test test.txt --color=always | cat 
test 
^ 
| 
|------- red again 
-1

A tener en cuenta aquí está el uso del comando script como un pseudo terminal ly ser detectado como un TTY en lugar de redirección (tubería) descriptor de archivo, consulte: bash command preserve color when piping

funciona como un encanto ...

De acuerdo con el ejemplo de la cuestión simplemente vamos script ejecutar cmake:

import subprocess 
proc = subprocess.Popen('script cmake', shell=True, stdout=subprocess.PIPE) 
while proc.poll() is None: 
    output = proc.stdout.readline() 
    print output 

Esto engaña a cmake haciéndole creer que se está ejecutando desde un terminal y producirá los caramelos ANSI que está buscando.

nJoy!

Cuestiones relacionadas