2012-01-23 7 views
10

Ho scritto uno script python semplice per la mia domanda e predefiniti alcuni comandi veloci come fare eccCome ottenere i dati di stdout dei sottoprocessi in modo asincrono?

ho scritto una funzione per l'esecuzione di comandi di 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')) 

tutto funziona bene tranne una poche cose:

  • sto usando cMake ed è uscita è colorato. Qualche possibilità di salvare i colori in uscita?

  • Posso osservare l'output dopo che il processo è terminato. Ad esempio, rendere viene eseguito per un lungo periodo di tempo, ma posso vedere l'output solo dopo la compilazione completa. Come farlo in modo asincrono?

risposta

12

io non sono sicuro di colori, ma ecco come eseguire il polling stdout una linea del sottoprocesso alla volta:

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

Non dimenticate di leggere da stderr così, come sono sicuro che cmake emetterà informazioni lì.

+0

Ok, grazie. Funziona. – Ockonal

2

Per quanto riguarda come ottenere l'output del processo prima che venga completata, dovrebbe essere possibile per farlo sostituire:

p.stdout.read 

con:

for line in p.stdout: 

Per quanto riguarda come salvare colorato uscita, non c'è niente di speciale in questo. Ad esempio, se l'output di riga viene salvato su un file, la volta successiva che viene eseguita la cat <logfile> la console interpreterà le sequenze di escape e visualizzerà i colori come previsto.

+0

con 'readline()' Ho un numero in fila invece di testo, cosa c'è che non va? – Ockonal

+1

@Ockonal In realtà se si usa il ciclo for, non è necessario usare 'readline'. È possibile trovare un esempio di entrambe le strategie [qui] (http://stackoverflow.com/q/2804543/183066). – jcollado

+0

In realtà 'per la riga in p.stdout' non è buono in Python 2 secondo http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line#comment11236752_2813530 –

0

Per fare asincrono di output fare qualcosa di simile: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

Non sono sicuro se è possibile catturare l'output colorato. Se riesci a ottenere i codici colore sfuggiti potresti essere in grado di farlo.

+0

Se otteniamo i codici colore, il terminale li tradurrà. Il problema però è che la maggior parte delle applicazioni distingue tra l'essere collegato a un terminale o il collegamento in un'altra applicazione. L'unico modo per convincere queste applicazioni a produrre ancora i codici colore è fingere che l'app ricevente (in questo caso il nostro processo python) sia in realtà una tty e non una pipe. Un compito molto più facile a dirsi che a farsi ... –

4

Non si ottiene il colore perché cmake rileva se il suo stdout è un terminale, se non lo è non colora il proprio output. Alcuni programmi ti danno la possibilità di forzare la colorazione. Sfortunatamente cmake no, quindi sei sfortunato. A meno che non si desideri patch cmake da soli.

Un sacco di programmi fanno questo, ad esempio grep:

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

Ora pipe al gatto:

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

grep opzione --color=always per forzare il colore:

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

Degne di nota ecco l'uso del comando script come una pseudo termina l ed essere rilevata come un terminale invece di reindirizzamento (tubo) descrittore di file, vedi: bash command preserve color when piping

funziona come un fascino ...

Come per l'esempio in questione semplicemente lasciare script eseguire cmake:

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

Questo trucco cmake è pensato per essere eseguito da un terminale e produrrà la caramella ANSI che stai cercando.

nJoy!

Problemi correlati