Jak używać polecenia `subprocess` z potokami

Odpowiedzi:

439

Aby użyć rury z subprocessmodułem, musisz przejść shell=True.

Nie jest to jednak zalecane z różnych powodów, między innymi z uwagi na bezpieczeństwo. Zamiast utworzyć psi grepprocesami oddzielnie, wyjście z rury jedna w drugą, tak jak poniżej:

ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait()

Jednak w twoim konkretnym przypadku prostym rozwiązaniem jest wywołanie, subprocess.check_output(('ps', '-A'))a następnie str.findwyjście.

Taymon
źródło
81
+1 za oddzielenie wyjścia / wejścia, aby uniknąć użyciashell=True
Nicolas
5
Nie zapominaj, błąd subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1oznacza po prostu, że grep nic nie znalazł, więc jest to normalne zachowanie.
Serge
2
Dlaczego potrzebujemy, ps.wait()kiedy mamy już dane wyjściowe. ps.wait.__doc__czeka na zakończenie przez dziecko, ale zawartość dziecka wydaje się już umieszczona w outputzmiennej
Papouche Guinslyzinho,
3
@MakisH Patrzysz string.find, co zostało przestarzałe na korzyść str.find(tj. Metody findna strobiektach).
Taymon
4
Uwaga: jeśli grepumrze przedwcześnie; psmoże zawiesić się na czas nieokreślony, jeśli wygeneruje wystarczającą moc wyjściową do wypełnienia bufora potoku systemu operacyjnego (ponieważ nie wywołano ps.stdout.close()elementu nadrzędnego). Zamień kolejność początkową, aby tego uniknąć
jfs
54

Lub zawsze możesz użyć metody komunikacji na obiektach podprocesu.

cmd = "ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

Metoda komunikacji zwraca krotkę standardowego wyjścia i standardowy błąd.

jkalivas
źródło
3
Myślę, że używanie communicatejest lepsze niż wait. Występuje takie ostrzeżenie: „Spowoduje to zakleszczenie przy użyciu stdout = PIPE i / lub stderr = PIPE, a proces potomny generuje wystarczającą moc wyjściową do potoku, tak że blokuje on oczekiwanie na bufor potoku systemu operacyjnego, aby zaakceptować więcej danych. unikaj tego ”.
Paolo,
2
Aby wyjaśnić powyższy komentarz Paolo, ostrzeżenie dotyczy oczekiwania, a nie komunikowania się - to jest powód, dla którego mówi, że komunikacja jest lepsza.
EnemyBagJones,
23

Zobacz dokumentację dotyczącą konfigurowania potoku za pomocą podprocesu: http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline

Nie testowałem następującego przykładu kodu, ale powinien on być mniej więcej taki, jak chcesz:

query = "process_name"
ps_process = Popen(["ps", "-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close()  # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0]
AlcubierreDrive
źródło
2
Po sprawdzeniu tego nie powiodła się, patrz odpowiedź poniżej Taymon za coś, co działa bez mucking
Alvin
2
Subprocess.check_output nie wydaje się istnieć w Pythonie 2.6.9
RightmireM
6

Rozwiązanie JKALAVIS jest dobre, ale dodałbym ulepszenie do używania shlex zamiast SHELL = TRUE. poniżej przedstawiam czasy zapytania

#!/bin/python
import subprocess
import shlex

cmd = "dig @8.8.4.4 +notcp www.google.com|grep 'Query'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)
Daniel Smith
źródło
1
Dlaczego Shellx over Shell?
AFP_555,
2
gdzie jest używany shlex?
3lokh
4

Spróbuj także użyć 'pgrep'polecenia zamiast'ps -A | grep 'process_name'

Shooe
źródło
2
jeśli chcesz uzyskać identyfikator procesu, oczywiście
Shooe,
3

Możesz wypróbować funkcjonalność potoku w sh.py :

import sh
print sh.grep(sh.ps("-ax"), "process_name")
amoffat
źródło
-1

Po Python 3.5 możesz także używać:

    import subprocess

    f = open('test.txt', 'w')
    process = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE, universal_newlines=True)
    f.write(process.stdout)
    f.close()

Wykonanie polecenia blokuje, a dane wyjściowe będą przetwarzane . Proces .

zingi
źródło