Вызов внешних команд
Простейший вариант использования использует subprocess.call
функцию. Он принимает список в качестве первого аргумента. Первым элементом в списке должно быть внешнее приложение, которое вы хотите вызвать. Другие элементы в списке являются аргументами, которые будут переданы этому приложению.
subprocess.call([r'C:\path\to\app.exe', 'arg1', '--flag', 'arg'])
Для команд оболочки, установленной shell=True
и обеспечить команду в виде строки , а не списка.
subprocess.call('echo "Hello, world"', shell=True)
Обратите внимание , что две команды выше возврата только exit status
подпроцесса. Кроме того, обратите внимание при использовании shell=True
, так как она обеспечивает проблемы безопасности (см здесь ).
Если вы хотите , чтобы иметь возможность получить стандартный вывод подпроцесса, то подставим subprocess.call
с subprocess.check_output
.Для более опытных пользователей, обратитесь к этим .
Больше гибкости с Popen
Использование subprocess.Popen
дает более мелкозернистую контроль над запущенными процессами , чем subprocess.call
.
Запуск подпроцесса
process = subprocess.Popen([r'C:\path\to\app.exe', 'arg1', '--flag', 'arg'])
Сигнатура Popen
очень похожа на call
функцию; Однако, Popen
немедленно вернуться вместо того , чтобы ждать подпроцесса для завершения , как call
делает.
Ожидание завершения подпроцесса
process = subprocess.Popen([r'C:\path\to\app.exe', 'arg1', '--flag', 'arg'])
process.wait()
Чтение вывода из подпроцесса
process = subprocess.Popen([r'C:\path\to\app.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# This will block until process completes
stdout, stderr = process.communicate()
print stdout
print stderr
Интерактивный доступ к запущенным подпроцессам
Вы можете читать и писать на stdin
и stdout
, даже в то время как подпроцесс не завершена. Это может быть полезно при автоматизации функций в другой программе.
Запись в подпроцесс
process = subprocess.Popen([r'C:\path\to\app.exe'], stdout = subprocess.PIPE, stdin = subprocess.PIPE)
process.stdin.write('line of input\n') # Write input
line = process.stdout.readline() # Read a line from stdout
# Do logic on line read.
Тем не менее, если вам нужно только один набор входных и выходных, а не динамическое взаимодействие, вы должны использовать communicate()
, а не прямой доступом stdin
и stdout
.
Чтение потока из подпроцесса
Если вы хотите видеть вывод подпроцесса построчно, вы можете использовать следующий фрагмент:
process = subprocess.Popen(<your_command>, stdout=subprocess.PIPE)
while process.poll() is None:
output_line = process.stdout.readline()
в случае, если выходные данные подкоманды не имеют символа EOL, приведенный выше фрагмент не работает. Затем вы можете прочитать вывод за символом следующим образом:
process = subprocess.Popen(<your_command>, stdout=subprocess.PIPE)
while process.poll() is None:
output_line = process.stdout.read(1)
1
указывается в качестве аргумента к read
методу говорит чтение для чтения 1 знака времени. Вы можете указать, чтобы прочитать столько символов, сколько вы хотите, используя другой номер. Отрицательное число или 0 указывает на read
для чтения в виде одной строки до EOF не встречается ( см здесь ).
В обоих указанных выше фрагментов, то process.poll()
не является None
до подпроцесса отделки. Это используется для выхода из цикла, когда больше нет выходных данных для чтения.
Же процедура может быть применена к stderr
подпроцесса.
Как создать аргумент списка команд
Метод подпроцесса , что позволяет запускать команды нуждается в команде в виде списка ( по крайней мере , с помощью shell_mode=True
).
Правила для создания списка не всегда просты, особенно для сложных команд. К счастью, есть очень полезный инструмент , который позволяет делать это: shlex
.Самый простой способ создания списка для использования в качестве команды заключается в следующем:
import shlex
cmd_to_subprocess = shlex.split(command_used_in_the_shell)
Простой пример:
import shlex
shlex.split('ls --color -l -t -r')
out: ['ls', '--color', '-l', '-t', '-r']