Альтернатива в python для подпроцесса

Я пытаюсь написать script, который должен сделать много вызовов некоторым командам bash, разобрать и обработать выходы и, наконец, дать некоторый вывод.

Я использовал subprocess.Popen и subprocess.call

Если я понимаю, что правильные эти методы порождают bah-процесс, запустите команду, получите результат и затем запустите процесс.

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

Я чувствую, что это немного оптимизировало бы вызовы, так как нет установки и смены процесса bash. Или это не даст никаких преимуществ?

Ответ 1

Если я понимаю, что правильные эти методы порождают bah-процесс, запустите команду, получите результат и затем запустите процесс.

subprocess.Popen немного больше задействован. Он фактически создает поток ввода-вывода, чтобы избежать взаимоблокировок. См. https://www.python.org/dev/peps/pep-0324/:

A communicate(), что упрощает отправку данных stdin и чтение данных stdout и stderr без риска блокировок. Большинство людей знают о проблемах управления потоком, связанных с коммуникацией с детскими процессами, но не у всех есть терпение или умение писать полностью правильный и безрезультатный цикл выбора. Это означает, что многие приложения Python содержат условия гонки. Метод communicate() в стандартной библиотеке решает эту проблему.


Есть ли способ непрерывного выполнения процесса bash в фоновом режиме, а затем вызовы python могут просто перейти непосредственно к этому процессу?

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

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

Ответ 2

Я чувствую, что это немного оптимизировало бы вызовы, так как не было установки и удаления процесса bash.

subprocess никогда не запускает оболочку, если вы не зададите ее явно, например,

#!/usr/bin/env python
import subprocess

subprocess.check_call(['ls', '-l'])

Этот вызов запускает программу ls без вызова /bin/sh.

Или это не даст преимущества производительности?

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

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

Если вы хотите использовать bash как серверный процесс, то pexpect полезен для диалоговых взаимодействий с внешним процессом - хотя маловероятно, что это влияет на производительность. fabric позволяет запускать как локальные, так и удаленные команды (ssh).

Существуют и другие подпроцессные обертки, такие как sarge, которые могут анализировать конвейер, указанный в строке, без вызова оболочки, например, он позволяет кросс-платформенная поддержка синтаксиса bash -like (&&, ||, & в командных строках) или sh - полная замена subprocess в Unix, которая по умолчанию предоставляет TTY (кажется полнофункциональным, но оболочечный трубопровод менее прост.). Вы даже можете использовать синтаксис Python-ish BASHwards для запуска команд с xonsh shell. Опять же, маловероятно, что в большинстве случаев это влияет на производительность значимым образом.

Проблема запуска и взаимодействия с внешними процессами переносимым образом сложна - взаимодействие между процессами, трубами, ttys, сигналами, потоками, async. IO, буферизация в разных местах имеет грубые края. Введение нового пакета может усложнить ситуацию, если вы не знаете, как определенный пакет решает множество проблем, связанных с запуском команд оболочки.