2013-08-14 12 views
24

Chcę uruchomić narzędzie do liczenia słów w Linuksie, aby określić liczbę linii w pliku/var/log/syslog, więc mogę wykryć, że rośnie. Próbowałem różnych testów, a gdy otrzymam wyniki z powrotem z wc, zawiera zarówno liczbę linii, jak i polecenie (np. Var/log/syslog).Wyjście podprocesu Python3

Więc to powrót: 1338/var/log/syslog Ale chcę tylko liczbę linii, więc chcę się rozebrać do/var/log/część syslog, i po prostu 1338 roku

I próbowałem przekonwertować go na ciąg z testu bytowego, a następnie rozbierając wynik, ale bez radości. Ta sama historia dla konwersji na łańcuchy i stripping, dekodowanie itd. - wszystkie nie dają rezultatów, których szukam.

Oto kilka przykładów tego, co mam, z 1338 linii w syslog:

  • b'1338/var/log/syslog \ n”
  • 1338/var/log/syslog

Oto niektóre kodu testu pisałem spróbować złamać tę nakrętkę, ale nie rozwiązanie:

import subprocess 

#check_output returns byte string 
stdoutdata = subprocess.check_output("wc --lines /var/log/syslog", shell=True) 
print("2A stdoutdata: " + str(stdoutdata)) 
stdoutdata = stdoutdata.decode("utf-8") 
print("2B stdoutdata: " + str(stdoutdata))  
stdoutdata=stdoutdata.strip() 
print("2C stdoutdata: " + str(stdoutdata))  

wyjście z tego jest:

  • 2A stdoutdata: b'1338/var/log/syslog \ n”

  • 2B stdoutdata: 1338/var/log/syslog

  • 2C stdoutdata: 1338/var/log/syslog

  • 2D stdoutdata: 1338/var/log/syslog

Odpowiedz

39

Sugeruję używasz subprocess.getoutput(), ponieważ robi dokładnie to, co chcesz - uruchom polecenie w powłoce i uzyskaj jego string output (w przeciwieństwie do wyjścia byte string). Następnie możesz split on whitespace i pobrać pierwszy element ze zwróconej listy ciągów.

Spróbuj tego:

import subprocess 
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog") 
print("stdoutdata: " + stdoutdata.split()[0]) 
+0

Dzięki! Przetestowałem to i zadziałało. Zrobił wiele badań, nigdy nie widział. Dang! – user2565677

+3

Należy ostrzec, że 'subprocess.getoutput' należy do kategorii * starszych funkcji wywołania powłoki * (http://docs.python.org/3/library/subprocess.html#subprocess.getoutput). – pepr

+0

@pepr Ale co właściwie oznacza "dziedzictwo"? Nie widzę osi czasu do usunięcia, jak 3.5.0a0. (Może być zdefiniowany gdzie indziej?) – belacqua

8

Aby uniknąć powołując skorupek i dekodowania nazwy plików, które mogą być dowolną sekwencję bajtów (z wyjątkiem '\0') na * nix, można przekazać plik jako stdin:

import subprocess 

with open(b'/var/log/syslog', 'rb') as file: 
    nlines = int(subprocess.check_output(['wc', '-l'], stdin=file)) 
print(nlines) 

Możesz też zignorować wszystkie błędy dekodowania:

import subprocess 

stdoutdata = subprocess.check_output(['wc', '-l', '/var/log/syslog']) 
nlines = int(stdoutdata.decode('ascii', 'ignore').partition(' ')[0]) 
print(nlines) 
+0

Czy istnieje sposób na uzyskanie 'sys.stdout.encoding' w tym przypadku, więc przekazujemy to do dekodowania zamiast' ascii'? Co się stanie, jeśli 'subprocess.PIPE' stdout? –

+1

@Mr_and_Mrs_D byłoby źle zrobić: 1- nie pomoże w ogólnym przypadku (nazwa pliku może być sekwencją bajtów, która jest nieodnotowalna przez kodowanie znaków, jak to zostało wyraźnie powiedziane w odpowiedzi. Patrz PEP 383) 2- ascii pracuje tutaj (dekodować cyfry wydrukowane przez wc w dowolnym języku obsługiwanym przez Python) – jfs