2012-02-22 17 views
18

Ho un caso di voler eseguire il seguente comando shell in Python e ottenere l'output,Python - come eseguire i comandi della shell con pipe?

echo This_is_a_testing | grep -c test 

ho potuto utilizzare questo codice python per eseguire il comando shell sopra pitone,

>>> import subprocess 
>>> subprocess.check_output("echo This_is_a_testing | grep -c test", shell=True) 
'1\n' 

Tuttavia, come io non voglio usare il "= shell true" opzione, ho provato il seguente codice python,

>>> import subprocess 
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout) 
>>> p1.stdout.close() 
>>> p2.communicate() 
(None, None) 

mi chiedo perché l'uscita è "Nessuno" come Ho fatto riferimento alle descrizioni nella pagina Web: http://docs.python.org/library/subprocess.html#subprocess.PIPE

Avevo perso alcuni punti nel mio codice? Qualche suggerimento/idea? Grazie in anticipo.

+0

aggiornato la risposta – avasal

+0

correlati: [Come si usa subprocess.Popen per collegare più processi da tubi?] (http://stackoverflow.com/q/295459/4279) – jfs

risposta

23

Dal manuale:

per ottenere qualcosa di diverso da Nessuno nella tupla risultato, è necessario dare stdout = tubo e/o stderr = TUBO

p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout, stdout=subprocess.PIPE) 
25

Si prega di guardare qui:

>>> import subprocess 
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout) 
>>> 1 
p1.stdout.close() 
>>> p2.communicate() 
(None, None) 
>>> 

qui si ottiene 1 come risultato dopo aver scritto p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout), Non ignorare questa uscita nel contesto della tua domanda.

Se questo è ciò che si vuole, quindi passare stdout=subprocess.PIPE come argomento al secondo Popen:

>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "test"], stdin=p1.stdout, stdout=subprocess.PIPE) 
>>> p2.communicate() 
('This_is_a_testing\n', None) 
>>> 
+0

Ora so che per 'p2.communicate()' per funzionare, devo aggiungere 'stdout = subprocess.PIPE' nel codice' p2 = ... '. Grazie. – user1129812

+0

Come posso ottenere l'errore se succede nel risultato p1? Ecco la mia domanda, puoi aiutarci? http://stackoverflow.com/questions/40467105/how-to-catch-ping-error-with-python –

8
>>> import subprocess 

>>> mycmd=subprocess.getoutput('df -h | grep home | gawk \'{ print $1 }\' | cut -d\'/\' -f3') 

>>> mycmd 

'sda6' 

>>> 
+0

utilizza la shell internamente. OP ha esplicitamente detto: * "Non voglio usare l'opzione" shell = True "" * – jfs

+1

Grazie. Questo è esattamente quello che cerco quando cerco "*** come eseguire comandi di shell con pipe ***" in Python. – xpt

+2

Ho dovuto usare commands.getoutput invece di subprocess.getoutput per far funzionare questa funzione – Anake

1

Mentre la risposta accettata è corretta/lavoro, un'altra opzione sarebbe quella di utilizzare il metodo Popen.communicate() a passare qualcosa ad un processo stdin:

>>> import subprocess 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
>>> p2.communicate("This_is_a_testing") 
('1\n', None) 
>>> print p2.returncode 
0 
>>>> 

Questo risolve la necessità di eseguire un altro comando solo per reindirizzare è fuori mettere, se l'output è già noto nello script Python stesso.

Tuttavia, communicate ha l'effetto collaterale che attende il termine del processo. Se l'esecuzione asincrona è necessaria/desiderata utilizzando due processi potrebbe essere l'opzione migliore.

-1

Ho provato sh -c "echo 1| grep 1" e ci sono riuscito. in questo modo: result=subprocess.Popen(['sh','-c',"\"\"echo 1|grep 1\"\""], stdout=subprocess.PIPE).communicate()[0]

Problemi correlati