web-dev-qa-db-fra.com

Python - comment exécuter des commandes Shell avec pipe?

J'ai un cas pour vouloir exécuter la commande Shell suivante dans Python et obtenir la sortie,

echo This_is_a_testing | grep -c test

Je pourrais utiliser ce code python pour exécuter la commande Shell ci-dessus en python,

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

Cependant, comme je ne veux pas utiliser l'option "Shell = True", j'ai essayé le code 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)

Je me demande pourquoi la sortie est "None" car j'ai fait référence aux descriptions de la page Web: http://docs.python.org/library/subprocess.html#subprocess.PIPE

Avais-je manqué quelques points dans mon code? Une suggestion/idée? Merci d'avance.

32
user1129812

Du manuel:

pour obtenir autre chose que None dans le résultat Tuple, vous devez donner stdout = PIPE et/ou stderr = PIPE

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

Veuillez regarder ici:

>>> 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)
>>>

ici, vous obtenez 1 en sortie après avoir écrit p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout), N'ignorez pas cette sortie dans le contexte de votre question.

Si c'est ce que vous voulez, passez stdout=subprocess.PIPE En argument au deuxième 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)
>>>
31
avasal
>>> import subprocess

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

>>> mycmd 

'sda6'

>>>
19

Alors que la réponse acceptée est correcte/fonctionne, une autre option serait d'utiliser la méthode Popen.communicate() pour passer quelque chose à un stdin de processus:

>>> 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
>>>>

Cela résout le besoin d'exécuter une autre commande juste pour rediriger sa sortie, si la sortie est déjà connue dans le script python lui-même.

Cependant, communicate a pour effet secondaire d'attendre la fin du processus. Si une exécution asynchrone est nécessaire/souhaitée, l'utilisation de deux processus peut être la meilleure option.

5
dpr