Ответ на этот вопрос зависит от версии Python, которую вы используете.Самый простой подход заключается в использовании функции subprocess.check_output
:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
запускает одну программу, которая принимает в качестве входных данных только аргументы. 1 Возвращаетрезультат точно такой же, как напечатано до stdout
.Если вам нужно записать ввод в stdin
, перейдите к разделам run
или Popen
.Если вы хотите выполнить сложные команды оболочки, см. Примечание к shell=True
в конце этого ответа.
Функция check_output
работает почти во всех версиях Python, все еще широко используемых (2.7+). 2 Но для более поздних версий это уже не рекомендуемый подход.
Современные версии Python (3.5 или выше): run
Если выпри использовании Python 3.5 или выше и не требуется обратная совместимость , рекомендуется new run
функция .Он предоставляет очень общий высокоуровневый API для модуля subprocess
.Чтобы получить выходные данные программы, передайте флаг subprocess.PIPE
ключевому аргументу stdout
.Затем получите доступ к атрибуту stdout
возвращенного объекта CompletedProcess
:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Возвращаемое значение является объектом bytes
, поэтому, если вы хотите правильную строку, вы 'Вам нужно будет decode
.Предполагая, что вызываемый процесс возвращает строку в кодировке UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Все это может быть сжато до одной строки:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Если вы хотите передать ввод вstdin
процесса, передать объект bytes
в аргумент ключевого слова input
:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Вы можете зафиксировать ошибки, передав stderr=subprocess.PIPE
(перехват в result.stderr
) или stderr=subprocess.STDOUT
(перехват)до result.stdout
вместе с обычным выходом).Когда безопасность не имеет значения, вы также можете запускать более сложные команды оболочки, передавая shell=True
, как описано в примечаниях ниже.
Это добавляет немного сложности по сравнению со старым способом выполнения действий.Но я думаю, что это того стоит: теперь вы можете делать практически все, что вам нужно, с помощью только функции run
.
Более старые версии Python (2.7-3.4): check_output
Если вы используете более старую версию Python или вам нужна скромная обратная совместимость, вы, вероятно, можете использовать функцию check_output
, как кратко описано выше.Он доступен с Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Он принимает те же аргументы, что и Popen
(см. Ниже), и возвращает строку, содержащую выходные данные программы.В начале этого ответа приведен более подробный пример использования.В Python 3.5 и выше, check_output
эквивалентно выполнению run
с check=True
и stdout=PIPE
и возвращению только атрибута stdout
.
Вы можете передать stderr=subprocess.STDOUT
, чтобы убедиться, что сообщения об ошибках включены в возвращаемый вывод, но в некоторых версиях Python передача stderr=subprocess.PIPE
в check_output
может вызвать взаимоблокировки .Когда безопасность не имеет значения, вы также можете запускать более сложные команды оболочки, передавая shell=True
, как описано в примечаниях ниже.
Если вам нужно передать из stderr
или передать ввод процессу, check_output
не будет до задачи.См. Popen
примеры ниже в этом случае.
Сложные приложения и устаревшие версии Python (2.6 и ниже): Popen
Если вам нужна глубокая обратная совместимость или если вам требуется более сложная функциональность, чем обеспечивает check_output
, вы 'Придется работать напрямую с Popen
объектами, которые инкапсулируют низкоуровневый API для подпроцессов.
Конструктор Popen
принимает либо одну команду без аргументов, либо список , содержащий команду в качестве первого элемента, за которой следует любое количество аргументов, каждыйкак отдельный элемент в списке.shlex.split
может помочь разобрать строки в соответствующим образом отформатированных списках.Объекты Popen
также принимают хост с различными аргументами для управления процессами ввода-вывода и низкоуровневой конфигурации.
Для отправки ввода и вывода вывода, communicate
почти всегда является предпочтительным методом.Как в:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Или
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Если вы установили stdin=PIPE
, communicate
также позволяет передавать данные процессу через stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Примечание Ответ Аарона Холла , который указывает, что в некоторых системах вам может потребоваться установить stdout
, stderr
и stdin
все в PIPE
(или DEVNULL
) в заставить communicate
работать вообще.
В некоторых редких случаях вам может потребоваться сложный захват выходных данных в режиме реального времени. Vartec ответ предлагает путь вперед, но методы, отличные от communicate
, склонны к тупикам, если не используются осторожно.
Как и во всех вышеперечисленных функциях, когда безопасность не имеет значения, вы можете запускать более сложные команды оболочки, передавая shell=True
.
Примечания
1. Запуск команд оболочки: аргумент shell=True
Обычно каждый вызов run
, check_output
или конструктора Popen
выполняет отдельную программу . Это означает, что нет причудливых трубок в стиле Баш. Если вы хотите запускать сложные команды оболочки, вы можете передать shell=True
, который поддерживают все три функции.
Однако это поднимает проблем безопасности . Если вы делаете что-то большее, чем легкие сценарии, вам может быть лучше вызывать каждый процесс отдельно и передавать выходные данные каждого из них в качестве входных данных следующему через
run(cmd, [stdout=etc...], input=other_output)
Или
Popen(cmd, [stdout=etc...]).communicate(other_output)
Сильно искушение напрямую соединить трубы; сопротивляться этому. В противном случае вы, скорее всего, увидите тупики или будете делать такие хакерские вещи, как this .
2. Особенности Unicode
check_output
возвращает строку в Python 2, но объект bytes
в Python 3. Стоит потратить немного времени, чтобы узнать о Unicode , если вы этого еще не сделали.