Мне удалось успешно передать переменную команде, которая далее не транслируется:
from subprocess import Popen, PIPE
def exec_command(command, some_input):
proc = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE)
(stdout, stderr) = proc.communicate(input=some_input)
... но при попытке подключить его к другой команде с каналами (например, для конвейера tar, а затем для дальнейшего разделения каналов), он не работает:
from subprocess import Popen, PIPE
def exec_piped_command(command1, command2, some_input):
proc1 = Popen(command1, stdout=PIPE, stdin=PIPE)
proc2 = Popen(command1, stdin=proc1.stdout, stdout=PIPE)
(stdout, stderr) = proc2.communicate(input=some_input)[0]
Итак, как правильный способ сделать этот второй вариант? Похоже, проблема с указанным выше кодом заключается в том, что вход в команду proc2.communicate() не доходит до stdin-канала proc1? (Не уверен, хотя... к несчастью, я немного смущен синтаксисом подпроцесса...).
Одна из возможностей состоит в том, чтобы настроить всю команду, которая будет выполнена оболочкой (shell=True
, среди ключевых слов вашего вызова Popen()
... и только .communicate()
с концами всего конвейера ( ваш вход идет в команду1 stdin, а ваш stdout/stderr поступает из command2 stdout/stderr).
Более сложный, но мелкозернистый подход будет заключаться в использовании os.fork()
наряду с os.pipe()
и os.dup2()
и, возможно, с некоторыми os.fcntl()
вызовами для настройки ваших собственных подпроцессов, с вашим собственным пользовательским переполнением и любые требуемые характеристики блокировки/неблокирования, которые вам нужны в ваших файловых дескрипторах, а затем, наконец, используя ваши собственные функции os.exec*
в каждом из них.
Этот последний подход, очевидно, будет дублировать совсем немного кода, который уже находится в модуле subprocess
. Тем не менее, он предоставляет вам возможность выполнять некоторые из этих шагов по-разному способами, которые не отображаются через класс subprocess.Popen
.
Средней дорогой было бы сделать подкласс, который наследует от subprocess.Popen
Конечно, может быть предпочтительнее выполнять некоторые части этого конвейера через код и модули Python (такие как операции tar, gzip и split).