Использование 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
для безопасного разделения ввода.