Использование subprocess и pipes в Python: метод check_output()
Быстрый ответ
Для создания в Python цепочки команд можно использовать subprocess.Popen. Если вы хотите перенаправить стандартный вывод одной команды как вход для другой, используйте stdout=subprocess.PIPE. Ниже приведен код, который выполняет ту же операцию, что и ls | grep py в терминале:
from subprocess import Popen, PIPE
# Стандартный вывод команды 'ls' передается на вход 'grep'
ls = Popen(['ls'], stdout=PIPE)
grep = Popen(['grep', 'py'], stdin=ls.stdout, stdout=PIPE)
ls.stdout.close() # Закрываем вывод 'ls'
output, _ = grep.communicate() # Получаем результат
print(output.decode())
Здесь Popen формирует пайплайн команд, а communicate() служит для получения конечного результата.

Игры с оболочкой: Когда использовать shell=True
Параметр shell=True пригодится, если вам требуются возможности оболочки, такие как пайпы или перенаправление. Однако берегитесь: всегда проверяйте входные данные, чтобы избежать уязвимостей:
import subprocess
# Пайп команд через оболочку
output = subprocess.check_output('ls | grep py', shell=True)
print(output.decode('utf-8'))
Использовать shell=True стоит аккуратно, особенно если данные непроверенны.
Привлекательная эффективность с subprocess.run
subprocess.run() — это современный и удобный способ выполнения подпроцессов, который сразу предоставляет результаты:
import subprocess
result = subprocess.run(['grep', 'py'], capture_output=True, text=True)
print(result.stdout)
Про обработку исключений при ошибке выполнения команды позаботится параметр check=True: при любом неполадках он вызовет исключение:
try:
subprocess.run(['false'], check=True)
except subprocess.CalledProcessError:
print("Ой-ой, Хьюстон, у нас проблема.")
Обработка вывода как профессионал
Чтобы преобразовать байтовые данные в строки, используйте метод .decode():
output = subprocess.run(['ls'], stdout=subprocess.PIPE).stdout
print(output.decode('utf-8'))
Также удобен метод .communicate(), помогающий избежать проблем, связанных с stdout и stderr, предотвращая блокировки:
from subprocess import PIPE, Popen
proc = Popen(['your_cmd'], stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()
Переход между множеством процессов
При работе с несколькими подпроцессами важно правильно управлять потоками данных. Не забывайте закрывать stdout команды, которую более не используете:
from subprocess import Popen, PIPE
ps = Popen(['ps', '-A'], stdout=PIPE)
grep = Popen(['grep', 'process_name'], stdin=ps.stdout, stdout=PIPE)
ps.stdout.close() # Закрываем вывод 'ps'
output = grep.communicate()[0]
print(output.decode('utf-8'))
Упрощаем жизнь с sh.py
Модуль sh значительно упрощает работу с подпроцессами. Установите его через pip install sh и контролируйте процессы, как если бы вы писали обычные команды:
from sh import grep, ps
# Имитация команды 'ps -ax | grep process_name'
print(grep(ps("-ax"), "process_name"))
Изюминки в работе с subprocess
Работа со subprocess требует внимательности и точности, как и при создании гастрономических шедевров:
- Берегитесь переполнения буфера — слишком большой вывод может вызвать проблемы.
- Будьте аккуратны с переменными окружения при использовании
shell=False. - Не забывайте "убирать посуду" — убедитесь, что все "кастрюли" (пайпы) закрыты, чтобы избежать проблем с завершением процессов.
Визуализация
Работа в subprocess, нацеленная на создание пайплайна, похоже на строителя, передающего кирпичи для постройки здания:
`cmd1` 🔧 | `cmd2` 🔨 | `cmd3` 🛠️
Каждый символ | символизирует передачу "кирпича" (данных) от одного инструмента к другому.
import subprocess
result = subprocess.run('cmd1 | cmd2 | cmd3', shell=True, text=True, stdout=subprocess.PIPE)
Каждый шаг строительства приводит к завершению сооружения "здания" данных.
Безопасность – дело серьезное
Продумайте меры безопасности, когда работаете с подпроцессами, особенно когда используете shell=True:
- Проверяйте данные на предмет возможных уязвимостей.
- По возможности старайтесь обходиться без
shell=True. - Для безопасной обработки пользовательского ввода, предназначенного для
shell=True, используйтеshlex.split.
Как стать опытным мастером
Несколько советов, чтобы ваша работа с subprocess была стабильной и высокопроизводительной:
- Для простых задач используйте
runсcapture_output=Trueилиstdout=PIPE. - Для больших проектов вы можете записывать данные в файл или обрабатывать их пакетами.
- Сложные пайплайны лучше управлять, создавая непосредственно объекты
Popen.
Дополнительные советы и хитрости для опытного строителя
Чтобы добиться мастерства в работе с subprocess:
- Используйте контекстные менеджеры для более удобного управления процессами.
- Объединяйте stdout и stderr, используя
stderr=subprocess.STDOUT. - Изучите использование возвращаемых кодов для контроля за успешностью выполнения команд.
Полезные материалы
- subprocess — Управление подпроцессами — Документация Python 3.12.2 — официальная документация по управлению подпроцессами.
- Модуль subprocess: Оболочка программ Python – Real Python — полезный обзор, как лучше всего использовать
subprocess. - python – Как использовать команду
subprocessс пайпами – Stack Overflow — примеры и обсуждение использования пайпов. - Python Pipes для избежания оболочек — Документация советов безопасности OpenStack 0.0.1.dev265 — информация о проблемах безопасности при использовании
shell=True. - shlex — Простой лексический анализ — Документация Python 3.12.2 — руководство по использованию
shlexдля безопасного разделения ввода.


