Як використовувати команду `subprocess` з трубами


246

Я хочу використовувати subprocess.check_output()з ps -A | grep 'process_name'. Я пробував різні рішення, але поки нічого не вийшло. Хтось може мене керувати, як це зробити?



4
є psutilте, що дозволяє отримувати інформацію про процес портативно.
— jfs

Відповіді:


439

Щоб використовувати трубу з subprocessмодулем, вам потрібно пройти shell=True.

Однак це не дуже доцільно з різних причин, не в останню чергу - безпека. Натомість створіть psі grepпроцеси окремо, і передайте висновок один в інший, як:

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

Однак у вашому конкретному випадку просте рішення - зателефонувати, subprocess.check_output(('ps', '-A'))а потім str.findна вихід.


81
+1 для розділення виходу / входу, щоб уникнути використанняshell=True
— Nicolas

5
Не забувайте, помилка subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1просто означає, що греп нічого не знайшов, тому це нормальна поведінка.
— Серж

2
Навіщо нам це потрібно, ps.wait()коли у нас вже є вихід. ps.wait.__doc__чекає, коли дитина припинить, але вміст дитини, здається, вже розміщений у outputзмінній
— Papouche Guinslyzinho,

3
@MakisH Ви дивитесь string.find, що застаріло на користь str.find(тобто метод findна strоб'єктах).
— Таймон

4
зауважте: якщо grepвмирає передчасно; psможе зависати нескінченно, якщо він виробляє достатньо виводу, щоб заповнити його буфер труб ОС (тому що ви не зверталися ps.stdout.close()до батьків). Міняйте початковий порядок, щоб уникнути цього
— jfs

54

Або ви завжди можете використовувати метод спілкування на об'єктах підпроцесу.

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

Метод зв'язку повертає кордон стандартного виводу та стандартну помилку.


3
Я думаю, що використовувати communicateкраще, ніж wait. Існує таке попередження: "Це прийде в глухий кут при використанні stdout = PIPE та / або stderr = PIPE, і дочірній процес генерує достатній вихід на трубу, щоб заблокувати очікування, коли буфер труб ОС прийме більше даних. Використовуйте зв'язок () для уникати цього ".
— Паоло

2
Для уточнення коментаря Паоло вище, попередження - це чекати, а не спілкуватися - тобто це причина, за якою він говорить, що краще спілкуватися.
— EnemyBagJones

23

Дивіться документацію щодо налаштування трубопроводу за допомогою підпроцесу: http://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline

Я не перевіряв наступний приклад коду, але він повинен бути приблизно тим, що вам потрібно:

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]

2
Перевіривши це не вдалося, див. Відповідь Таймона нижче про те, що працює, не замислюючись
— Елвін

2
subprocess.check_output, здається, не існує в Python 2.6.9
— RightmireM

6

Рішення JKALAVIS добре, проте я б додав поліпшення для використання shlex замість SHELL = ІСТИНА. нижче імпортування разів запитів

#!/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)

1
Чому оболонка над оболонкою?
— AFP_555

2
де тут використовується шлекс?
— 3лох

4

Також спробуйте використовувати 'pgrep'команду замість'ps -A | grep 'process_name'


2
якщо ви хочете отримати ідентифікатор процесу, очевидно
— Shooe

3

Ви можете спробувати функціональність труби в sh.py :

import sh
print sh.grep(sh.ps("-ax"), "process_name")

-1

Після Python 3.5 ви також можете використовувати:

    import subprocess

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

Виконання команди блокується, і вихід буде в process.stdout .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.