2012-01-23 8 views
10

napisałem prosty skrypt Pythona do mojego wniosku i predefiniowane kilka szybkich komend jak zrobić itpJak asynchronicznie uzyskać subprocessowe dane wyjściowe?

pisałem funkcję do uruchamiania poleceń systemowych (Linux):

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

wszystko działa dobrze z wyjatkiem kilka rzeczy:

  • Używam cmake i to wyjście jest kolorowy. Jakieś szanse na zapisanie kolorów na wydruku?

  • Mogę sprawdzić dane wyjściowe po zakończeniu procesu. Na przykład powoduje, że działa przez dłuższy czas, ale widzę wyjście tylko po pełnej kompilacji. Jak to zrobić asynchronicznie?

Odpowiedz

12

nie jestem pewien o kolorach, ale oto jak do sondowania stdout jedną linię podprocesu za naraz:

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

Nie zapomnij przeczytać z stderr jak dobrze, że jestem pewien, cmake wyśle ​​tam informacje.

+0

OK, dziękuję. To działa. – Ockonal

2

chodzi jak uzyskać wyjście procesu przed jej zakończeniem, powinno być możliwe do zrobienia, że ​​zastąpienie:

p.stdout.read 

z:

for line in p.stdout: 

chodzi jak oszczędzać kolorowy wyjście, nie ma w tym nic specjalnego. Na przykład, jeśli wynik wiersza zostanie zapisany w pliku, następnym razem zostanie wykonana cat <logfile>, konsola zinterpretuje sekwencje specjalne i wyświetli kolory zgodnie z oczekiwaniami.

+0

z 'readline()' Mam liczby w wierszu zamiast tekstu, co jest nie tak? – Ockonal

+1

@Ockonal Właściwie jeśli używasz pętli for, nie ma potrzeby używania 'readline'. Możesz znaleźć przykład obu strategii [tutaj] (http://stackoverflow.com/q/2804543/183066). – jcollado

+0

W rzeczywistości 'dla linii w p.stdout' nie jest dobre w Pythonie 2 zgodnie z http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line#comment11236752_2813530 –

0

Aby zrobić wyjście asynchroniczny zrobić coś takiego: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

Nie wiem, czy można zrobić wyjście kolorową. Jeśli uda Ci się uzyskać kody kolorów ucieczkowych, możesz być w stanie.

+0

Po otrzymaniu kodów kolorów terminal przetłumaczy je. Problem polega jednak na tym, że większość aplikacji rozróżnia między dołączaniem do terminala lub podłączeniem do innej aplikacji. Jedynym sposobem, aby przekonać te aplikacje, aby nadal generowały kody kolorów, jest fałszowanie, że aplikacja odbierająca (w tym przypadku nasz proces python) jest w rzeczywistości tty, a nie fajką. Zadanie o wiele łatwiej powiedzieć niż zrobić ... –

4

Nie dostaniesz koloru, ponieważ cmake wykrywa, czy jego standardowe wyjście jest terminalem, jeśli nie, nie zabarwia własnego wyjścia. Niektóre programy dają możliwość wymuszenia wydruków. Niestety cmake nie ma, więc nie masz szczęścia. Chyba że sam chcesz łatać łatkę cmake.

Wiele programów to zrobić, na przykład, grep:

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

Teraz rury go do kota:

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

grep opcję --color=always zmusić kolor:

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

Warto zauważyć, tutaj jest użycie polecenia script jako pseudo-termina l i być wykrywany jako tty zamiast przekierowania (rury) deskryptor pliku, patrz: bash command preserve color when piping

działa jak czar ...

Jak na przykład w kwestii po prostu niech script wykonać cmake:

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

Ta sztuczka cmake na myślenie, że jest wykonywana z terminala i będzie produkować cukierek ANSI, którego szukasz.

nJoy!