Python - как выполнить команды оболочки с трубы? - PullRequest
32 голосов
/ 22 февраля 2012

У меня есть случай, когда я хочу выполнить следующую команду оболочки в Python и получить вывод,

echo This_is_a_testing | grep -c test

Я мог бы использовать этот код Python для выполнения вышеуказанной команды оболочки в python,

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

Однако, поскольку я не хочу использовать опцию «shell = True», я попробовал следующий код 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)

Интересно, почему вывод «Нет», как у меняссылается на описания на веб-странице: http://docs.python.org/library/subprocess.html#subprocess.PIPE

Неужели я пропустил некоторые пункты в своем коде?Любое предложение / идея?Заранее спасибо.

Ответы [ 4 ]

31 голосов
/ 22 февраля 2012

Пожалуйста, посмотрите здесь:

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

здесь вы получите 1 в качестве вывода после того, как напишите p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout), не игнорируйте этот вывод в контексте вашего вопроса.

Если это то, что вы хотите, то передайте stdout=subprocess.PIPE в качестве аргумента второму 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)
>>>
26 голосов
/ 22 февраля 2012

Из руководства:

, чтобы получить что-либо кроме None в кортеже результата, вам нужно указать stdout = PIPE и / или stderr = PIPE

p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout, stdout=subprocess.PIPE)
17 голосов
/ 14 сентября 2015
>>> import subprocess

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

>>> mycmd 

'sda6'

>>>
5 голосов
/ 22 сентября 2016

В то время как принятый ответ является правильным / рабочим, другой вариант мог бы использовать метод Popen.communicate() для передачи чего-либо процессу '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
>>>>

Это решает необходимость выполнения другой команды простоперенаправить вывод, если вывод уже известен в самом скрипте python.

Однако communicate имеет побочный эффект, который ожидает завершения процесса.Если асинхронное выполнение необходимо / желательно, использование двух процессов может быть лучшим вариантом.

...