Модуль subprocess — Работаем с процессами

Модуль subprocess дает разработчику возможность запускать процессы программ из Python. Другим словами, вы можете запускать приложения и передавать им аргументы при помощи модуля subprocess. Модуль subprocess был внедрен в Python 2.4 для замены настроек вызовов модуля os, таких как os.popen, os.spawn и os.system, а также для замены popen2 и старых командных модулей. В данной статье мы взглянем на следующие аспекты модуля subprocess:

  • Функция вызова;
  • Класс Popen;
  • Как связываться с созданным процессом.

Приступим к делу!

Функция вызова call

Модуль subprocess python содержит функцию под названием call. Эта функция позволяет вам вызывать другую программу, дожидаться завершения команды и вернуть код возврата. Она принимает один или несколько аргументов, а также следует ключевым аргументам (с их значениями): stdin=None, stdout=None, stderr=None, shell=False.
Взглянем на простой пример:

Если вы запустите этот код на машине, которая работает на Windows Python, вы увидите открывшийся блокнот. Обратите внимание на то, что IDLE ожидает, пока вы закроете блокнот, после чего вернет нулевой код (0).

Это значит, что код был выполнен успешно. Если вы получите что-либо, что не является ноль, то вы столкнулись с какой-то ошибкой. Как правило, когда вы вызываете эту функцию, вам, возможно, требуется назначить итоговой выдаче кода переменную, чтобы проверить, получили ли вы ожидаемый результат. Давайте сделаем это:

Если вы запустите этот код, вы увидите надпись Success! Метод call также принимает аргументы, для передачи программе, которую вы выполняете. Давайте взглянем на то, как это работает:

Результат

Обратите внимание на то, что в данном примере мы передали список аргументов. Первый объект в списке это программа, которую мы хотим вызвать. Все остальное в списке – это аргументы, которые мы хотим передать программе. Так что в данном примере мы выполняем пинг на сайте Yahoo. Также обратите внимание на то, что код возврата нулевой, так что все прошло успешно. Поздравляю. Вы также можете выполнить программу, используя оболочку операционной системы. Это повысит уровень абстракции в процессе, а также повышает риск возникновения проблем с безопасностью. На эту тему в документации есть небольшое предупреждение:

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Выполнение необработанных вводных данных из ненадежного источника делает программу уязвимой для внедрений в оболочку, что является серьезным недостатком безопасности, который может привести к произвольному исполнению команд. По этой причине, применение shell=True настоятельно не рекомендуется в случаях, когда командная строка создана во внешнем входе.

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

Класс Popen

Класс Popen Python выполняет дочернюю программу в новом процессе. В отличие от метода call, он не дожидается конца выполнения вызванного процесса, если вы не укажете это в методе wait. Давайте попробуем запустить блокнот через Popen и посмотрим, в чем разница:

Здесь мы создали переменную под названием program и назначили ей значение notepad.exe. После этого мы передали её классу Popen. После запуска этого кода, вы увидите, что он мгновенно вернет объект subprocess.Popen, а вызванное приложение будет выполняться. Давайте попросим Popen дождаться, когда программа закончит:

Делая это в IDLE, то блокнот всплывет и может быть перед вашей сессией IDLE. Просто перетащите его, но не закрывайте! Вам нужно указать вашему процессу подождать, пока вы не получите код возврата. После того, как вы впишете эту строку, закройте блокнот и впишите код. Или вы можете просто поместить весь код в сохраненный файл Python и запустить его. Обратите внимание на то, что использование метода wait может вызвать блокировку дочернего процесса при использовании команды stdout/stderr=PIPE, когда процесс генерирует достаточно выходных данных для блокировки pipe. Вы можете использовать метод communicate, для смягчения этой ситуации. Мы рассмотрим этот метод в будущем. Теперь попробуем запустить Popen при помощи нескольких аргументов:

Если вы запустите этот код в Linux, вы увидите возникшее сообщение объекта Popen, затем перечень разрешений и содержимого той или иной папки, которую вы используете. Вы можете использовать аргумент shell совместно с Popen, но с теми же предостережениями, что и с методом call.

Как связываться с созданным процессом

Существует несколько способов связаться с созданным вами процессом. Мы сфокусируемся на том, как использовать метод communicate модуля subprocess. Давайте взглянем:

На примере данного кода, мы создали переменную args, которая содержит список наших аргументов. После этого мы перенаправили stdout на наш subprocess, так что теперь мы можем связаться с ним. Метод communicate позволяет нам связываться с созданным нами процессом. Мы также можем передать процессу ввод при помощи данного метода. Но в нашем примере, мы используем этот метод для чтения stdout. Обратите внимание на то, что когда вы запускаете этот код, цель которого – поддержка связи, он будет дожидаться финиша процесса, После чего выдаст кортеж, состоящий из двух элементов, которые являются содержимым stdout и stderr. Вот результат:

Это немного уродливо выглядит. Давайте сделаем выдачу чуть более читабельной.

Если вы запустите этот код, вы увидите что-то на манер этой выдачи на экране:

Последняя строчка говорит, что None – это результат stderr, а это значит, что ошибок не найдено.

Подведем итоги

С этого момента, вы обладаете всеми необходимыми для использования модуля subprocess знаниями. Вы можете открывать процесс двумя разными способами, знаете как дожидаться кода возврата, и вы знаете как связываться с дочерним процессом, который вы создали.