Как выполнить программу или вызвать системную команду?

Как вызвать внешнюю команду (как если бы я набрал ее в оболочке Unix или в командной строке Windows) из сценария Python?


person freshWoWer    schedule 18.09.2008    source источник


Ответы (61)


Используйте модуль subprocess в стандартной библиотеке:

import subprocess
subprocess.run(["ls", "-l"])

Преимущество subprocess.run перед _ 4_ заключается в том, что он более гибкий (вы можете получить _ 5_, _ 6_, реальный код состояния, улучшенная обработка ошибок и т. д. ).

Даже документация для os.system рекомендует вместо этого использовать subprocess:

Модуль subprocess предоставляет более мощные средства для создания новых процессов и получения их результатов; использование этого модуля предпочтительнее, чем использование этой функции. См. Раздел Замена старых функций модулем подпроцесса в _ 10_ документацию для некоторых полезных рецептов.

В Python 3.4 и ранее используйте subprocess.call вместо .run:

subprocess.call(["ls", "-l"])
person David Cournapeau    schedule 18.09.2008
comment
Есть ли способ использовать подстановку переменных? IE Я попытался сделать echo $PATH с помощью call(["echo", "$PATH"]), но он просто повторил буквальную строку $PATH вместо выполнения какой-либо подстановки. Я знаю, что могу получить переменную среды PATH, но мне интересно, есть ли простой способ заставить команду вести себя точно так, как если бы я выполнил ее в bash. - person Kevin Wheeler; 02.09.2015
comment
@KevinWheeler. Чтобы это сработало, вам нужно использовать shell=True. - person SethMMorton; 02.09.2015
comment
@KevinWheeler Вы НЕ должны использовать shell=True, для этой цели Python поставляется с os.path.expandvars. В вашем случае вы можете написать: os.path.expandvars("$PATH"). @SethMMorton, пожалуйста, пересмотрите свой комментарий - ›Почему бы не использовать shell = Верно - person Murmel; 11.11.2015

Вот краткое изложение способов вызова внешних программ, а также преимущества и недостатки каждого из них:

  1. os.system("some_command with args") передает команду и аргументы в оболочку вашей системы. Это хорошо, потому что вы можете одновременно запускать несколько команд таким образом и настраивать каналы и перенаправление ввода / вывода. Например:

     os.system("some_command < input_file | another_command > output_file")  
    

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

  1. stream = os.popen("some_command with args") будет делать то же самое, что и os.system, за исключением того, что он предоставляет вам объект в виде файла, который вы можете использовать для доступа к стандартному вводу / выводу для этого процесса. Есть еще 3 варианта popen, которые обрабатывают ввод-вывод немного по-разному. Если вы передадите все как строку, ваша команда будет передана оболочке; если вы передадите их в виде списка, вам не нужно беспокоиться о том, чтобы от чего-либо уйти. См. документацию.

  2. Класс Popen модуля subprocess. Он предназначен для замены os.popen, но имеет обратную сторону - он немного сложнее в силу того, что он настолько всеобъемлющий. Например, вы бы сказали:

     print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
    

вместо того:

    print os.popen("echo Hello World").read()

но приятно иметь все параметры в одном унифицированном классе вместо 4 различных функций popen. См. документацию.

  1. Функция call из модуля subprocess. По сути, он похож на класс Popen и принимает все те же аргументы, но просто ждет, пока команда завершится, и выдаст вам код возврата. Например:

     return_code = subprocess.call("echo Hello World", shell=True)  
    

    См. документацию.

  2. Если вы используете Python 3.5 или новее, вы можете использовать новый subprocess.run < / a>, которая очень похожа на приведенную выше, но еще более гибкая и возвращает CompletedProcess после завершения выполнения команды.

  3. Модуль os также имеет все функции fork / exec / spawn, которые есть в программе на C, но я не рекомендую использовать их напрямую.

Модуль subprocess, вероятно, должен быть тем, что вы используете.

Наконец, имейте в виду, что для всех методов, в которых вы передаете последнюю команду, которая должна выполняться оболочкой в ​​виде строки, вы несете ответственность за ее экранирование. Если какой-либо части передаваемой строки нельзя полностью доверять, это может серьезно повлиять на безопасность. Например, если пользователь вводит некоторую / любую часть строки. Если вы не уверены, используйте эти методы только с константами. Чтобы дать вам представление о последствиях, рассмотрим этот код:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

и представьте, что пользователь вводит что-то, что моя мама меня не любила && rm -rf /, что может стереть всю файловую систему.

person Eli Courtwright    schedule 18.09.2008
comment
Хороший ответ / объяснение. Как этот ответ оправдывает девиз Python, описанный в этой статье? fastcompany.com/3026446/ Стилистически Perl и Python имеют разные философии. Самый известный девиз Perl - «Есть более чем один способ сделать это». Python разработан таким образом, чтобы иметь один очевидный способ сделать это. Кажется, должно быть наоборот! В Perl я знаю только два способа выполнить команду - с помощью обратного тика или open. - person Jean; 27.05.2015
comment
Если вы используете Python 3.5+, используйте subprocess.run(). docs.python.org/3.5/library/subprocess.html#subprocess. запустить - person phoenix; 07.10.2015
comment
Обычно нужно знать, что делается с STDOUT и STDERR дочернего процесса, потому что, если они игнорируются при некоторых (довольно распространенных) условиях, в конечном итоге дочерний процесс выдаст системный вызов для записи в STDOUT (STDERR тоже?) это превысит выходной буфер, предоставленный для процесса ОС, и ОС заставит его блокироваться до тех пор, пока какой-либо процесс не прочитает из этого буфера. Итак, с рекомендуемыми в настоящее время способами, subprocess.run(..), что именно подразумевает This не захватывает stdout или stderr по умолчанию.? А как насчет subprocess.check_output(..) и STDERR? - person Evgeni Sergeev; 01.06.2016
comment
какая из команд, которые вы рекомендовали, блокирует мой скрипт? т.е. если я хочу запустить несколько команд в цикле for, как мне это сделать, чтобы он не блокировал мой скрипт Python? Меня не волнует вывод команды, я просто хочу запустить их много. - person Charlie Parker; 24.10.2017
comment
@phoenix Я не согласен. Ничто не мешает вам использовать os.system в docs.python3 python3. org / 3 / library / os.html # os.system - person Qback; 08.12.2017
comment
Возможно, это неправильный путь. Большинству людей нужен только subprocess.run() или его старшие братья и сестры subprocess.check_call() и др. В случаях, когда этого недостаточно, см. subprocess.Popen(). os.popen(), возможно, не следует упоминать вообще или появиться даже после взлома вашего собственного кода fork / exec / spawn. - person tripleee; 03.12.2018

Типовая реализация:

import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

Вы можете делать что хотите с stdout данными в канале. Фактически, вы можете просто опустить эти параметры (stdout= и stderr=), и он будет вести себя как os.system().

person EmmEff    schedule 18.09.2008
comment
.readlines() читает все строки сразу, т.е. блокируется до тех пор, пока подпроцесс не завершится (закрывает свой конец канала). Чтобы читать в реальном времени (если нет проблем с буферизацией), вы можете: for line in iter(p.stdout.readline, ''): print line, - person jfs; 16.11.2012
comment
Не могли бы вы пояснить, что вы имеете в виду, если нет проблем с буферизацией? Если процесс определенно блокируется, вызов подпроцесса также блокируется. То же самое могло произойти и с моим исходным примером. Что еще может случиться с буферизацией? - person EmmEff; 17.11.2012
comment
дочерний процесс может использовать блочную буферизацию в неинтерактивном режиме вместо буферизации строк, поэтому p.stdout.readline() (примечание: нет s в конце) не увидит никаких данных, пока дочерний процесс не заполнит свой буфер. Если ребенок не производит много данных, результат не будет в реальном времени. См. Вторую причину в Q: Почему бы просто не использовать канал (popen ())?. Некоторые обходные пути представлены в этом ответе (pexpect, pty, stdbuf) - person jfs; 17.11.2012
comment
проблема с буферизацией имеет значение только в том случае, если вы хотите выводить данные в реальном времени, и не относится к вашему коду, который ничего не печатает, пока не будут получены все данные - person jfs; 17.11.2012
comment
Этот ответ был хорош для своего времени, но мы больше не должны рекомендовать Popen для простых задач. Здесь также без необходимости указывается shell=True. Попробуйте один из subprocess.run() ответов. - person tripleee; 03.12.2018

Некоторые подсказки по отсоединению дочернего процесса от вызывающего (запуск дочернего процесса в фоновом режиме).

Предположим, вы хотите запустить длинную задачу из сценария CGI. То есть дочерний процесс должен жить дольше, чем процесс выполнения сценария CGI.

Классический пример из документации модуля подпроцесса:

import subprocess
import sys

# Some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess

# Some more code here

Идея здесь в том, что вы не хотите ждать в строке «call subprocess», пока longtask.py не завершится. Но непонятно, что происходит после строки «еще немного кода» из примера.

Моей целевой платформой была FreeBSD, но разработка велась в Windows, поэтому сначала я столкнулся с проблемой в Windows.

В Windows (Windows XP) родительский процесс не завершится, пока longtask.py не завершит свою работу. Это не то, что вам нужно в сценарии CGI. Проблема не является специфической для Python; в сообществе PHP проблемы те же.

Решение состоит в том, чтобы передать DETACHED_PROCESS Создание процесса Отметьте базовую функцию CreateProcess в Windows API. Если вы установили pywin32, вы можете импортировать флаг из модуля win32process, в противном случае вы должны определить его самостоятельно:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/ * UPD 2015.10.27 @eryksun в комментарии ниже отмечает, что семантически правильный флаг - CREATE_NEW_CONSOLE (0x00000010) * /

Во FreeBSD у нас есть еще одна проблема: когда родительский процесс завершается, он также завершает дочерние процессы. И это не то, что вам нужно в сценарии CGI. Некоторые эксперименты показали, что проблема заключалась в совместном использовании sys.stdout. И рабочее решение было таким:

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

Я не проверял код на других платформах и не знаю причин такого поведения на FreeBSD. Если кто знает, поделитесь, пожалуйста, своими идеями. Поиск в Google по запуску фоновых процессов в Python пока не проливает света.

person newtover    schedule 12.02.2010
comment
Я заметил возможную причуду при разработке приложений py2exe в pydev + eclipse. я смог сказать, что основной скрипт не был отсоединен, потому что окно вывода eclipse не закрывалось; даже если сценарий выполняется до конца, он все еще ожидает возврата. но когда я попытался скомпилировать исполняемый файл py2exe, происходит ожидаемое поведение (процессы запускаются как отсоединенные, а затем завершаются). Я не уверен, но имени исполняемого файла больше нет в списке процессов. это работает для всех подходов (os.system (start *), os.spawnl с os.P_DETACH, subprocs и т. д.) - person maranas; 09.04.2010
comment
Попадание в Windows: хотя я создал процесс с помощью DETACHED_PROCESS, когда я убил своего демона Python, все порты, открытые им, не освободились, пока все порожденные процессы не завершились. WScript.Shell решил все мои проблемы. Пример здесь: pastebin.com/xGmuvwSx - person Alexey Lebedev; 16.04.2012
comment
вам также может понадобиться флаг CREATE_NEW_PROCESS_GROUP. См. Popen, ожидающий дочернего процесса, даже если непосредственный дочерний процесс завершился - person jfs; 16.11.2012
comment
Я вижу import subprocess as sp;sp.Popen('calc') не дожидаясь завершения подпроцесса. Кажется, что флаги создания не нужны. Что мне не хватает? - person ubershmekel; 28.10.2014
comment
@ubershmekel, я не понимаю, что вы имеете в виду, и у меня нет установки Windows. Если я правильно помню, без флагов вы не можете закрыть экземпляр cmd, из которого вы запустили calc. - person newtover; 28.10.2014
comment
Я использую Windows 8.1, и calc, похоже, пережил закрытие python. - person ubershmekel; 30.10.2014
comment
Имеет ли значение использование «0x00000008»? Это конкретное значение, которое необходимо использовать, или один из нескольких вариантов? - person SuperBiasedMan; 05.05.2015
comment
Следующее неверно: [o] n windows (win xp), родительский процесс не завершится, пока longtask.py не завершит свою работу. Родительский процесс завершится нормально, но окно консоли (экземпляр conhost.exe) закрывается только при выходе из последнего присоединенного процесса, а потомок, возможно, унаследовал родительскую консоль. Установка DETACHED_PROCESS в creationflags позволяет избежать этого, не позволяя дочернему элементу наследовать или создавать консоль. Если вместо этого вам нужна новая консоль, используйте CREATE_NEW_CONSOLE (0x00000010). - person Eryk Sun; 27.10.2015
comment
Я не имел в виду, что выполнение как отдельного процесса некорректно. Тем не менее, вам может потребоваться установить стандартные дескрипторы для файлов, каналов или os.devnull, потому что в противном случае некоторые консольные программы завершаются с ошибкой. Создайте новую консоль, если вы хотите, чтобы дочерний процесс взаимодействовал с пользователем одновременно с родительским процессом. Было бы непросто попытаться сделать и то, и другое в одном окне. - person Eryk Sun; 27.10.2015
comment
stdout=subprocess.PIPE заставит ваш код зависнуть, если у вас долгий вывод от ребенка. Для получения дополнительной информации см. thraxil .org / users / anders / posts / 2008/03/13 / - person Dr_Zaszuś; 08.03.2018
comment
нет ли независимого от ОС способа запустить процесс в фоновом режиме? - person Charlie Parker; 24.02.2019
comment
мне ваш ответ кажется странным. Я только что открыл subprocess.Popen, и ничего плохого не произошло (не пришлось ждать). Почему именно нам нужно беспокоиться о сценарии, который вы указываете? Я настроен скептически. - person Charlie Parker; 24.02.2019

import os
os.system("your command")

Обратите внимание, что это опасно, поскольку команда не очищается. Я оставляю на ваше усмотрение поиск в Google соответствующей документации по модулям 'os' и 'sys'. Есть несколько функций (exec * и spawn *), которые будут делать похожие вещи.

person nimish    schedule 18.09.2008
comment
Понятия не имею, что я имел в виду почти десять лет назад (проверьте дату!), Но если бы я должен был догадаться, это было бы так, что не было сделано никакой проверки. - person nimish; 06.06.2018
comment
Теперь это должно указывать на subprocess как на более универсальное и портативное решение. Выполнение внешних команд, конечно, по своей сути непереносимо (вы должны убедиться, что команда доступна для каждой архитектуры, которую вам нужно поддерживать), а передача пользовательского ввода в качестве внешней команды по своей сути небезопасна. - person tripleee; 03.12.2018
comment
Обратите внимание на временную метку этого парня: за правильный ответ в 40 раз больше голосов, и это ответ №1. - person nimish; 03.12.2018
comment
Единственное решение, которое сработало для меня для работы с NodeJS. - person Nikolay Shindarov; 29.10.2019

Я бы рекомендовал использовать модуль subprocess вместо os.system, поскольку он выполняет экранирование оболочки для вы и поэтому намного безопаснее.

subprocess.call(['ping', 'localhost'])
person sirwart    schedule 18.09.2008
comment
Если вы хотите создать список из команды с параметрами, список, который можно использовать с subprocess, когда shell=False, используйте shlex.split, чтобы упростить это docs.python.org/2/library/shlex.html#shlex.split (это рекомендуемый способ в соответствии с документами docs.python.org/2/library/ subprocess.html # popen-constructor) - person Daniel F; 20.09.2018
comment
Это неверно: он выполняет экранирование оболочки за вас и, следовательно, намного безопаснее. subprocess не выполняет экранирование оболочки, подпроцесс не передает вашу команду через оболочку, поэтому нет необходимости в экранировании оболочки. - person Lie Ryan; 04.12.2018

import os
cmd = 'ls -al'
os.system(cmd)

Если вы хотите вернуть результаты команды, вы можете использовать _2 _ . Однако с версии 2.6 это устарело в пользу модуля подпроцесса, которые хорошо освещены в других ответах.

person Alexandra Franks    schedule 18.09.2008
comment
popen устарел в пользу подпроцесс. - person Tris Emmy Wilson; 08.08.2014
comment
Вы также можете сохранить свой результат с помощью вызова os.system, поскольку он работает как сама оболочка UNIX, например, os.system ('ls -l ›test2.txt') - person Stefan Gruenwald; 08.11.2017

Существует множество различных библиотек, которые позволяют вызывать внешние команды с помощью Python. Для каждой библиотеки я дал описание и показал пример вызова внешней команды. В качестве примера я использовал команду ls -l (перечислить все файлы). Если вы хотите узнать больше о любой из библиотек, я перечислил и связал документацию для каждой из них.

Источники

Это все библиотеки

Надеюсь, это поможет вам решить, какую библиотеку использовать :)

подпроцесс

Подпроцесс позволяет вызывать внешние команды и подключать их к их каналам ввода / вывода / ошибок (stdin, stdout и stderr). Подпроцесс - это выбор по умолчанию для запуска команд, но иногда лучше подходят другие модули.

subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command

os

os используется для функций, зависящих от операционной системы. Его также можно использовать для вызова внешних команд с os.system и os.popen (Примечание: существует также subprocess.popen). os всегда будет запускать оболочку и является простой альтернативой для людей, которым это не нужно или которые не знают, как использовать subprocess.run.

os.system("ls -l") # Run command
os.popen("ls -l").read() # This will run the command and return any output

sh

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

sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function

отвес

plumbum - это библиотека для программ Python, подобных скриптам. Вы можете вызывать программы как функции, как в sh. Plumbum полезен, если вы хотите запустить конвейер без оболочки.

ls_cmd = plumbum.local("ls -l") # Get command
ls_cmd() # Run command

ожидание

pexpect позволяет создавать дочерние приложения, управлять ими и находить закономерности в их выводе. Это лучшая альтернатива подпроцессу для команд, ожидающих tty в Unix.

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo [email protected]:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')

ткань

fabric - это библиотека Python 2.5 и 2.7. Он позволяет выполнять локальные и удаленные команды оболочки. Fabric - простая альтернатива для запуска команд в защищенной оболочке (SSH).

fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output

посланник

посланник известен как подпроцесс для людей. Он используется как удобная оболочка для модуля subprocess.

r = envoy.run("ls -l") # Run command
r.std_out # Get output

команды

commands содержит функции-оболочки для os.popen, но он был удален из Python 3, поскольку subprocess - лучшая альтернатива.

person Tom Fuller    schedule 29.10.2016

Со стандартной библиотекой

Используйте модуль подпроцесса (Python 3):

import subprocess
subprocess.run(['ls', '-l'])

Это рекомендуемый стандартный способ. Однако создание и написание более сложных задач (конвейеры, вывод, ввод и т. Д.) Может быть утомительным.

Примечание по версии Python: если вы все еще используете Python 2, подпроцесс .call работает аналогичным образом.

Подсказка: shlex.split может помочь вам разобрать команда для run, call и других subprocess функций на случай, если вы не хотите (или не можете!) предоставлять их в виде списков:

import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

С внешними зависимостями

Если вы не возражаете против внешних зависимостей, используйте plumbum:

from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())

Это лучшая subprocess обертка. Он кроссплатформенный, т.е. работает как в Windows, так и в Unix-подобных системах. Установить с помощью pip install plumbum.

Еще одна популярная библиотека - sh:

from sh import ifconfig
print(ifconfig('wlan0'))

Однако sh отказался от поддержки Windows, так что это уже не так здорово, как раньше. Установить pip install sh.

person Community    schedule 11.04.2013

Я всегда использую fabric для таких вещей, как:

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

Но это, похоже, хороший инструмент: sh (интерфейс подпроцесса Python).

Взгляните на пример:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
person Jorge E. Cardona    schedule 13.03.2012

Также проверьте библиотеку Python "pexpect".

Он позволяет интерактивно управлять внешними программами / командами, даже ssh, ftp, telnet и т. Д. Вы можете просто ввести что-то вроде:

child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password')
person athanassis    schedule 07.10.2010

Если вам нужны выходные данные вызываемой команды, вы можете использовать подпроцесс .check_output (Python 2.7+).

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

Также обратите внимание на параметр shell.

Если оболочка True, указанная команда будет выполняться через оболочку. Это может быть полезно, если вы используете Python в первую очередь для расширенного потока управления, который он предлагает для большинства системных оболочек, и по-прежнему хотите удобный доступ к другим функциям оболочки, таким как каналы оболочки, подстановочные знаки имен файлов, расширение переменных среды и расширение ~ до дома пользователя каталог. Однако обратите внимание, что сам Python предлагает реализации многих функций, подобных оболочке (в частности, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser() и shutil).

person Facundo Casco    schedule 28.04.2011
comment
Обратите внимание, что check_output требуется список, а не строка. Если вы не полагаетесь на пробелы в кавычках, чтобы сделать ваш вызов действительным, самый простой и читаемый способ сделать это - subprocess.check_output("ls -l /dev/null".split()). - person Bruno Bronosky; 30.01.2018
comment
Как неясно упоминается ответ, и многие другие ответы на этой странице объясняют более подробно, вы можете передать список или с shell=True одну строку, которую оболочка затем позаботится о синтаксическом анализе и выполнении. Использование простого .split() нормально в упомянутых вами обстоятельствах, но новички обычно не понимают нюансов; вам, вероятно, лучше порекомендовать shlex.split(), который правильно обрабатывает кавычки и экранирование обратной косой черты. - person tripleee; 09.06.2021

Обновлять:

subprocess.run - рекомендуемый подход начиная с Python 3.5, если ваш код поддерживает нет необходимости поддерживать совместимость с более ранними версиями Python. Он более последовательный и предлагает ту же простоту использования, что и Envoy. (Однако трубопровод не так прост. См. этот вопрос, чтобы узнать, как.)

Вот несколько примеров из документации.

Запустить процесс:

>>> subprocess.run(["ls", "-l"])  # Doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

Рейз при неудачном беге:

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Вывод захвата:

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

Оригинальный ответ:

Я рекомендую попробовать Envoy. Это оболочка для подпроцесса, которая, в свою очередь, призвана заменить старые модули и функции. . Посланник - это подпроцесс для людей.

Пример использования из README:

>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''

Трубка тоже:

>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[<Response 'uptime'>]
person Joe    schedule 15.11.2012

Вот как я запускаю свои команды. В этом коде есть все, что вам нужно в значительной степени

from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()
person Usman Khan    schedule 28.10.2012
comment
Я думаю, что это приемлемо для жестко запрограммированных команд, если это увеличивает читаемость. - person Adam Matan; 02.04.2014
comment
Объяснение было бы в порядке. Например, в чем идея / суть? - person Peter Mortensen; 07.04.2021

Используйте подпроцесс.

... или для очень простой команды:

import os
os.system('cat testfile')
person Ben Hoffstein    schedule 18.09.2008

Как выполнить программу или вызвать системную команду из Python

Просто используйте subprocess.run, который возвращает объект CompletedProcess:

>>> from subprocess import run
>>> from shlex import split
>>> completed_process = run(split('python --version'))
Python 3.8.8
>>> completed_process
CompletedProcess(args=['python', '--version'], returncode=0)

(run требуется список аргументов оболочки, проанализированных лексически - это то, что вы должны ввести в оболочке, разделенные пробелами, но не там, где пробелы заключены в кавычки, поэтому используйте специальную функцию split, чтобы разделить то, что вы буквально набираете в вашу оболочку)

Почему?

Начиная с Python 3.5, в документации рекомендуется subprocess.run:

Рекомендуемый подход к вызову подпроцессов - использовать функцию run () для всех возможных вариантов использования. Для более сложных случаев использования можно напрямую использовать базовый интерфейс Popen.

Вот пример простейшего возможного использования - и он делает именно то, что просили:

>>> from subprocess import run
>>> from shlex import split
>>> completed_process = run(split('python --version'))
Python 3.8.8
>>> completed_process
CompletedProcess(args=['python', '--version'], returncode=0)

run ожидает успешного завершения команды, затем возвращает объект CompletedProcess. Вместо этого он может поднять TimeoutExpired (если вы дадите ему timeout= аргумент) или CalledProcessError (если он не сработает и вы передадите check=True).

Как вы можете заключить из приведенного выше примера, оба stdout и stderr по умолчанию передаются на ваш собственный stdout и stderr.

Мы можем проверить возвращенный объект и увидеть заданную команду и код возврата:

>>> completed_process.args
['python', '--version']
>>> completed_process.returncode
0

Захват вывода

Если вы хотите записать вывод, вы можете передать subprocess.PIPE соответствующему stderr или stdout:

>>> from subprocess import PIPE
>>> completed_process = run(shlex.split('python --version'), stdout=PIPE, stderr=PIPE)
>>> completed_process.stdout
b'Python 3.8.8\n'
>>> completed_process.stderr
b''

И эти соответствующие атрибуты возвращают байты.

Передайте список команд

Можно легко перейти от предоставления командной строки вручную (как предполагает вопрос) к предоставлению строки, созданной программно. Не создавайте строки программным способом. Это потенциальная проблема безопасности. Лучше предположить, что вы не доверяете вводимым данным.

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\n  This is indented.\n'

Обратите внимание, что только args следует передавать позиционно.

Полная подпись

Вот фактическая подпись в источнике, как показано help(run):

def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

popenargs и kwargs передаются конструктору Popen. input может быть строкой байтов (или Unicode, если указать кодировку или universal_newlines=True), которые будут переданы на стандартный ввод подпроцесса.

Документация описывает timeout= и check=True лучше, чем я мог бы:

Аргумент тайм-аута передается в Popen.communicate (). Если время ожидания истечет, дочерний процесс будет убит и будет ждать. Исключение TimeoutExpired будет повторно вызвано после завершения дочернего процесса.

Если проверка верна и процесс завершается с ненулевым кодом выхода, возникает исключение CalledProcessError. Атрибуты этого исключения содержат аргументы, код выхода и stdout и stderr, если они были захвачены.

и этот пример для check=True лучше, чем тот, который я мог придумать:

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Расширенная подпись

Вот расширенная подпись, как указано в документации:

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

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

Popen

Когда вместо этого использовать Popen? Я бы изо всех сил пытался найти вариант использования, основанный только на аргументах. Однако прямое использование Popen даст вам доступ к его методам, включая poll, send_signal, terminate и wait.

Вот подпись Popen, указанная в источнике. Я думаю, что это наиболее точная инкапсуляция информации (в отличие от help(Popen)):


def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=True,
             shell=False, cwd=None, env=None, universal_newlines=None,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, user=None, group=None, extra_groups=None,
             encoding=None, errors=None, text=None, umask=-1, pipesize=-1):

Но более информативным является Popen документация:

subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, 
stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None,
env=None, universal_newlines=None, startupinfo=None, creationflags=0, 
restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, 
extra_groups=None, user=None, umask=-1, encoding=None, errors=None, 
text=None)

Выполнить дочернюю программу в новом процессе. В POSIX класс использует поведение, подобное os.execvp (), для выполнения дочерней программы. В Windows класс использует функцию Windows CreateProcess (). Аргументы в пользу Попена следующие.

Понимание остальной документации по Popen будет оставлено читателю в качестве упражнения.

person Aaron Hall    schedule 18.10.2017
comment
Простой пример двусторонней связи между основным процессом и подпроцессом можно найти здесь: stackoverflow.com/a/52841475/1349673 < / а> - person James Hirschorn; 16.10.2018

os.system в порядке, но несколько устарело. Это тоже не очень безопасно. Вместо этого попробуйте subprocess. subprocess не вызывает sh напрямую и поэтому более безопасен, чем os.system.

Дополнительную информацию см. здесь.

person Martin W    schedule 18.09.2008
comment
Хотя я согласен с общей рекомендацией, subprocess не устраняет всех проблем безопасности и имеет некоторые собственные неприятные проблемы. - person tripleee; 03.12.2018

Также есть Plumbum

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns
person stuckintheshuck    schedule 10.10.2014
comment
Объяснение было бы в порядке. - person Peter Mortensen; 07.04.2021

Начиная с Python 3.7.0, выпущенного 27 июня 2018 г. (https://docs.python.org/3/whatsnew/3.7.html), вы можете достичь желаемого результата самым эффективным и в то же время простым способом. Этот ответ призван вкратце показать вам основное резюме различных вариантов. Более подробные ответы можно найти в других.


TL;DR in 2021

Большим преимуществом os.system(...) была его простота. subprocess лучше и по-прежнему прост в использовании, особенно с Python 3.5.

import subprocess
subprocess.run("ls -a", shell=True)

Примечание. Это точный ответ на ваш вопрос - выполнение команды.

как в раковине


Предпочтительный способ

Если возможно, удалите служебные данные оболочки и запустите команду напрямую (требуется список).

import subprocess
subprocess.run(["help"])
subprocess.run(["ls", "-a"])

Передайте аргументы программы в виде списка. Не используйте \"-экранирование для аргументов, содержащих пробелы.


Расширенные варианты использования

Проверка вывода

Следующий код говорит сам за себя:

import subprocess
result = subprocess.run(["ls", "-a"], capture_output=True, text=True)
if "stackoverflow-logo.png" in result.stdout:
    print("You're a fan!")
else:
    print("You're not a fan?")

result.stdout - это нормальный вывод программы, исключая ошибки. Прочтите result.stderr, чтобы получить их.

capture_output=True - включает захват. В противном случае result.stderr и result.stdout были бы None. Доступно в Python 3.7.

text=True - удобный аргумент, добавленный в Python 3.7, который преобразует полученные двоичные данные в строки Python, с которыми вы можете легко работать.

Проверка кода возврата

Do

if result.returncode == 127: print("The program failed for some weird reason")
elif result.returncode == 0: print("The program succeeded")
else: print("The program failed unexpectedly")

Если вы просто хотите проверить, удалась ли программа (код возврата == 0), а в противном случае выбросить исключение, есть более удобная функция:

result.check_returncode()

Но это Python, поэтому есть еще более удобный аргумент, check который делает то же самое автоматически за вас:

result = subprocess.run(..., check=True)

stderr должен быть внутри stdout

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

result = subprocess.run(..., stderr=subprocess.STDOUT)

result.stderr тогда будет None, а result.stdout будет содержать все.

Использование shell = False со строкой аргумента

shell=False ожидает список аргументов. Однако вы можете самостоятельно разделить строку аргумента с помощью shlex.

import subprocess
import shlex
subprocess.run(shlex.split("ls -a"))

Вот и все.

Общие проблемы

Скорее всего, вы только что начали использовать Python, когда столкнетесь с этим вопросом. Давайте посмотрим на некоторые общие проблемы.

FileNotFoundError: [Errno 2] Нет такого файла или каталога: 'ls -a': 'ls -a'

Вы запускаете подпроцесс без shell=True. Либо используйте список (["ls", "-a"]), либо установите shell=True.

TypeError: [...] NoneType [...]

Убедитесь, что вы установили capture_output=True.

TypeError: требуется объект, похожий на байты, а не [...]

Вы всегда получаете результат в байтах от вашей программы. Если вы хотите работать с ним как с обычной строкой, установите text=True.

subprocess.CalledProcessError: Команда '[...]' вернула ненулевой статус выхода 1.

Ваша команда не выполнена. Вы можете отключить проверку кода возврата или проверить действительность вашей программы.

TypeError: init () получил неожиданный аргумент ключевого слова [...]

Вы, вероятно, используете версию Python старше 3.7.0; обновите его до самого последнего доступного. В противном случае в этом сообщении о переполнении стека есть другие ответы, в которых показаны более старые альтернативные решения.

person fameman    schedule 13.10.2020
comment
Большим преимуществом os.system (...) была ее простота. subprocess лучше - как subprocess лучше? Я с удовольствием использую os.system, не знаю, как мне выгодно переключение на подпроцесс и запоминание дополнительных shell=True. Что лучше в подпроцессе? - person reducing activity; 26.03.2021
comment
Вы правы в том, что os.system(...) - разумный выбор для выполнения команд с точки зрения простого слепого выполнения. Однако варианты использования довольно ограничены - как только вы хотите захватить вывод, вам нужно использовать целую другую библиотеку, а затем вы начинаете иметь как подпроцесс, так и ОС для аналогичных вариантов использования в вашем коде. Я предпочитаю держать код в чистоте и использовать только один из них. Во-вторых, и я бы поместил этот раздел вверху, но TL; DR должен ответить на вопрос точно, вы должны не использовать shell=True, а вместо этого то, что я написано в разделе Preferred Way. - person fameman; 27.03.2021
comment
Проблема с os.system(...) и shell=True заключается в том, что вы создаете новый процесс оболочки, просто чтобы выполнить свою команду. Это означает, что вам нужно выполнить экранирование вручную, что не так просто, как вы думаете, особенно при ориентации как на POSIX, так и на Windows. Для пользовательского ввода это недопустимо (просто представьте, что пользователь ввел что-то с " кавычками - вам также придется их избегать). Кроме того, сам процесс оболочки может загружать ненужный вам код - это не только задерживает выполнение программы, но также может привести к неожиданным побочным эффектам, заканчивающимся неправильным кодом возврата. - person fameman; 27.03.2021
comment
Подводя итог, os.system(...) действительно можно использовать. Но как только вы напишете нечто большее, чем простой вспомогательный скрипт на Python, я бы порекомендовал вам использовать subprocess.run без shell=True. Для получения дополнительной информации о недостатках os.system я хотел бы предложить вам прочитать этот ответ SO: stackoverflow.com/a / 44731082/6685358 - person fameman; 27.03.2021
comment
Благодарность! Я хотел лучше отредактировать, чтобы включить эту ссылку, но у меня возникла ошибка о полной очереди редактирования. - person reducing activity; 27.03.2021

Это может быть так просто:

import os
cmd = "your command"
os.system(cmd)
person Samadi Salahedine    schedule 30.04.2018
comment
Это не указывает на недостатки, которые более подробно описаны в PEP-324.. В документации для os.system явно рекомендуется избегать этого в пользу subprocess. - person tripleee; 03.12.2018

Использовать:

import os

cmd = 'ls -al'

os.system(cmd)

os - этот модуль обеспечивает переносимый способ использования функций, зависящих от операционной системы.

Документацию по дополнительным os функциям можно найти здесь.

person Priyankara    schedule 29.06.2015
comment
он также устарел. использовать подпроцесс - person Corey Goldberg; 09.12.2015

Здесь есть еще одно отличие, о котором ранее не упоминалось.

subprocess.Popen выполняет ‹команду> как подпроцесс. В моем случае мне нужно запустить файл ‹a>, который должен взаимодействовать с другой программой ‹b>.

Я попробовал подпроцесс, и выполнение прошло успешно. Однако ‹b> не смог связаться с ‹a>. Все нормально, когда оба запускаю с терминала.

Еще одно: (ПРИМЕЧАНИЕ: kwrite ведет себя иначе, чем другие приложения. Если вы попробуете описанное ниже с Firefox, результаты не будут такими же.)

Если вы попробуете os.system("kwrite"), выполнение программы зависнет, пока пользователь не закроет kwrite. Чтобы преодолеть это, я попробовал вместо этого os.system(konsole -e kwrite). На этот раз программа продолжала работать, но kwrite стал подпроцессом консоли.

Любой запускает kwrite, не являющийся подпроцессом (т.е. в системном мониторе он должен отображаться на крайнем левом краю дерева).

person Atinc Delican    schedule 08.01.2010
comment
Что вы имеете в виду под Кто-нибудь запускает kwrite, не являясь подпроцессом? - person Peter Mortensen; 03.06.2018
comment
Это действительно сбивает с толку, что subprocess запускает подпроцесс. - person tripleee; 09.06.2021

os.system не позволяет вам сохранять результаты, поэтому, если вы хотите сохранить результаты в каком-либо списке или чем-то еще, subprocess.call работает.

person Saurabh Bangad    schedule 11.06.2012

subprocess.check_call удобно, если вы не хотите проверять возвращаемые значения. При любой ошибке генерируется исключение.

person cdunn2001    schedule 18.01.2011

Я обычно использую подпроцесс вместе с shlex (для обработки экранирования строк в кавычках):

>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)
person Emil Stenström    schedule 30.04.2014

Я написал для этого библиотеку shell.py.

На данный момент это в основном обертка для popen и shlex. Он также поддерживает команды конвейера, поэтому вы можете упростить цепочку команд в Python. Таким образом, вы можете делать такие вещи, как:

ex('echo hello shell.py') | "awk '{print $2}'"
person houqp    schedule 01.05.2014

В Windows вы можете просто импортировать модуль subprocess и запускать внешние команды, вызывая subprocess.Popen(), subprocess.Popen().communicate() и subprocess.Popen().wait(), как показано ниже:

# Python script to run a command line
import subprocess

def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    rc = process.wait()

    if rc != 0:
        print "Error: failed to execute command:", cmd
        print error
    return result
# def

command = "tasklist | grep python"
print "This process detail: \n", execute(command)

Выход:

This process detail:
python.exe                     604 RDP-Tcp#0                  4      5,660 K
person Swadhikar    schedule 17.06.2016

В Linux, если вы хотите вызвать внешнюю команду, которая будет выполняться независимо (продолжит выполнение после завершения сценария Python), вы можете использовать простую очередь как диспетчер очереди задач или по команде.

Пример с диспетчером очереди задач:

import os
os.system('ts <your-command>')

Примечания о диспетчере очереди задач (ts):

  1. Вы можете установить количество одновременно запускаемых процессов (слотов) с помощью:

    ts -S <number-of-slots>

  2. Для установки ts не требуются права администратора. Вы можете загрузить и скомпилировать его из исходного кода с помощью простого make, добавить его в свой путь, и все готово.

person Yuval Atzmon    schedule 27.11.2016
comment
ts не является стандартом ни в одном известном мне дистрибутиве, хотя указатель на at в некоторой степени полезен. Вам, вероятно, также следует упомянуть batch. Как и везде, в рекомендации os.system(), вероятно, следует хотя бы упомянуть, что subprocess является рекомендуемой заменой. - person tripleee; 03.12.2018

Вы можете использовать Popen, а затем вы можете проверить статус процедуры:

from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill()

Ознакомьтесь с subprocess.Popen.

person admire    schedule 16.07.2012

Чтобы получить идентификатор сети из OpenStack Neutron:

#!/usr/bin/python
import os
netid = "nova net-list | awk '/ External / { print $2 }'"
temp = os.popen(netid).read()  /* Here temp also contains new line (\n) */
networkId = temp.rstrip()
print(networkId)

Вывод nova net-list

+--------------------------------------+------------+------+
| ID                                   | Label      | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1      | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External   | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal   | None |
+--------------------------------------+------------+------+

Вывод print (networkId)

27a74fcd-37c0-4789-9414-9531b7e3f126
person IRSHAD    schedule 20.07.2016
comment
Не рекомендуется рекомендовать os.popen() в 2016 году. Скрипт Awk можно легко заменить собственным кодом Python. - person tripleee; 03.12.2018

Invoke - это инструмент и библиотека для выполнения задач Python (2.7 и 3.4+). Он предоставляет чистый высокоуровневый API для запуска команд оболочки:

>>> from invoke import run
>>> cmd = "pip install -r requirements.txt"
>>> result = run(cmd, hide=True, warn=True)
>>> print(result.ok)
True
>>> print(result.stdout.splitlines()[-1])
Successfully installed invocations-0.13.0 pep8-1.5.7 spec-1.3.1
person Valery Ramusik    schedule 14.09.2018
comment
Это отличная библиотека. На днях я пытался объяснить это коллеге, и я описал это так: invoke для subprocess, как requests для urllib3. - person user9074332; 12.03.2019

Простой способ - использовать модуль os:

import os
os.system('ls')

В качестве альтернативы вы также можете использовать модуль подпроцесса:

import subprocess
subprocess.check_call('ls')

Если вы хотите, чтобы результат сохранялся в переменной, попробуйте:

import subprocess
r = subprocess.check_output('ls')
person amehta    schedule 24.08.2014

Самый простой способ запустить любую команду и вернуть результат:

from commands import getstatusoutput

try:
    return getstatusoutput("ls -ltr")
except Exception, e:
    return None
person Garfield    schedule 25.07.2012
comment
Будет ли это устаревшим в Python 3.0? - person 719016; 04.03.2014
comment
Действительно, в commands документации Python 2.7 говорится, что он устарел в версии 2.6 и будет быть удаленным в 3.0. - person tripleee; 03.12.2018

В большинстве случаев:

В большинстве случаев вам может понадобиться такой короткий фрагмент кода:

import subprocess
import shlex

source = "test.txt"
destination = "test_copy.txt"

base = "cp {source} {destination}'"
cmd = base.format(source=source, destination=destination)
subprocess.check_call(shlex.split(cmd))

Это чисто и просто.

subprocess.check_call запустить команду с аргументами и дождаться завершения команды.

shlex.split разделить строку cmd, используя синтаксис, подобный оболочке

ОТДЫХ СЛУЧАЕВ:

Если это не работает для какой-то конкретной команды, скорее всего, у вас проблема с command- линейные переводчики. Операционная система выбрала программу по умолчанию, которая не подходит для вашего типа программы или не смогла найти подходящую в системном пути к исполняемому файлу.

Пример:

Использование оператора перенаправления в системе Unix

input_1 = "input_1.txt"
input_2 = "input_2.txt"
output = "merged.txt"
base_command = "/bin/bash -c 'cat {input} >> {output}'"

base_command.format(input_1, output=output)
subprocess.check_call(shlex.split(base_command))

base_command.format(input_2, output=output)
subprocess.check_call(shlex.split(base_command))

Как указано в Дзен Python: Явное лучше, чем неявное

Таким образом, если использовать функцию Python ›= 3.6, это будет выглядеть примерно так:

import subprocess
import shlex

def run_command(cmd_interpreter: str, command: str) -> None:
    base_command = f"{cmd_interpreter} -c '{command}'"
    subprocess.check_call(shlex.split(base_command)

person N.Nonkovic    schedule 28.11.2019

Часто я использую следующую функцию для внешних команд, и это особенно удобно для длительных процессов. Приведенный ниже метод отслеживает вывод процесса во время выполнения и возвращает вывод, вызывает исключение в случае сбоя процесса.

Он появляется, если процесс выполняется с использованием метода poll () для процесса.

import subprocess,sys

def exec_long_running_proc(command, args):
    cmd = "{} {}".format(command, " ".join(str(arg) if ' ' not in arg else arg.replace(' ','\ ') for arg in args))
    print(cmd)
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline().decode('UTF-8')
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise Exception(command, exitCode, output)

Вы можете вызвать его так:

exec_long_running_proc(command = "hive", args=["-f", hql_path])
person am5    schedule 23.03.2018
comment
Вы получите неожиданные результаты, передав аргумент с пробелом. Использование repr(arg) вместо str(arg) может помочь по простому совпадению, поскольку python и sh экранируют кавычки одинаково - person sbk; 17.05.2018
comment
@sbk repr(arg) не особо помог, приведенный выше код также обрабатывает пробелы. Сейчас работает exec_long_running_proc(command = "ls", args=["-l", "~/test file*"]) - person am5; 17.11.2018

Вот мои два цента: На мой взгляд, это лучшая практика при работе с внешними командами ...

Это возвращаемые значения из метода execute ...

pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop")

Это метод выполнения ...

def execute(cmdArray,workingDir):

    stdout = ''
    stderr = ''

    try:
        try:
            process = subprocess.Popen(cmdArray,cwd=workingDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
        except OSError:
            return [False, '', 'ERROR : command(' + ' '.join(cmdArray) + ') could not get executed!']

        for line in iter(process.stdout.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stdout += echoLine

        for line in iter(process.stderr.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stderr += echoLine

    except (KeyboardInterrupt,SystemExit) as err:
        return [False,'',str(err)]

    process.stdout.close()

    returnCode = process.wait()
    if returnCode != 0 or stderr != '':
        return [False, stdout, stderr]
    else:
        return [True, stdout, stderr]
person Community    schedule 14.10.2015
comment
Потенциал взаимоблокировки: вместо этого используйте метод .communicate - person pppery; 07.07.2016
comment
А еще лучше избегать Popen() и использовать API более высокого уровня, который теперь объединен в единую функцию subprocess.run() - person tripleee; 03.12.2018

Я написал небольшую библиотеку, чтобы помочь с этим вариантом использования:

https://pypi.org/project/citizenshell/

Его можно установить с помощью

pip install citizenshell

А потом использовали так:

from citizenshell import sh
assert sh("echo Hello World") == "Hello World"

Вы можете отделить стандартный вывод от стандартной ошибки и извлечь код выхода следующим образом:

result = sh(">&2 echo error && echo output && exit 13")
assert result.stdout() == ["output"]
assert result.stderr() == ["error"]
assert result.exit_code() == 13

И что самое интересное, вам не нужно ждать завершения работы основной оболочки, прежде чем начать обработку вывода:

for line in sh("for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done", wait=False)
    print ">>>", line + "!"

напечатает строки, поскольку они доступны благодаря wait = False

>>> It is 14:24:52!
>>> It is 14:24:53!
>>> It is 14:24:54!
>>> It is 14:24:55!

Дополнительные примеры можно найти на странице https://github.com/meuter/citizenshell.

person Cédric    schedule 30.10.2018


Вызов внешней команды в Python

Простой способ вызвать внешнюю команду - использовать os.system(...). И эта функция возвращает значение выхода команды. Но недостаток в том, что мы не получим stdout и stderr.

ret = os.system('some_cmd.sh')
if ret != 0 :
    print 'some_cmd.sh execution returned failure'

Вызов внешней команды в Python в фоновом режиме

subprocess.Popen обеспечивает большую гибкость для запуска внешней команды вместо использования os.system. Мы можем запустить команду в фоновом режиме и дождаться ее завершения. И после этого мы можем получить stdout и stderr.

proc = subprocess.Popen(["./some_cmd.sh"], stdout=subprocess.PIPE)
print 'waiting for ' + str(proc.pid)
proc.wait()
print 'some_cmd.sh execution finished'
(out, err) = proc.communicate()
print 'some_cmd.sh output : ' + out

Вызов длительной внешней команды в Python в фоновом режиме и остановка через некоторое время

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

proc = subprocess.Popen(["./some_long_run_cmd.sh"], stdout=subprocess.PIPE)
# Do something else
# Now some_long_run_cmd.sh exeuction is no longer needed, so kill it
os.system('kill -15 ' + str(proc.pid))
print 'Output : ' proc.communicate()[0]
person rashok    schedule 04.04.2018

Использовать:

import subprocess

p = subprocess.Popen("df -h", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")

Это дает хороший результат, с которым легче работать:

['Filesystem      Size  Used Avail Use% Mounted on',
 '/dev/sda6        32G   21G   11G  67% /',
 'none            4.0K     0  4.0K   0% /sys/fs/cgroup',
 'udev            1.9G  4.0K  1.9G   1% /dev',
 'tmpfs           387M  1.4M  386M   1% /run',
 'none            5.0M     0  5.0M   0% /run/lock',
 'none            1.9G   58M  1.9G   3% /run/shm',
 'none            100M   32K  100M   1% /run/user',
 '/dev/sda5       340G  222G  100G  69% /home',
 '']
person David Okwii    schedule 24.06.2016

В качестве примера (в Linux):

import subprocess
subprocess.run('mkdir test.dir', shell=True)

Это создает test.dir в текущем каталоге. Обратите внимание, что это также работает:

import subprocess
subprocess.call('mkdir test.dir', shell=True)

Эквивалентный код с использованием os.system:

import os
os.system('mkdir test.dir')

Лучшей практикой было бы использовать subprocess вместо os, при этом .run предпочтительнее .call. Все, что вам нужно знать о подпроцессе, находится здесь. Также обратите внимание, что всю документацию Python можно загрузить с здесь. Я скачал PDF в формате .zip. Я упоминаю об этом, потому что есть хороший обзор модуля os в tutorial.pdf (стр. 81). Кроме того, это авторитетный ресурс для программистов Python.

person Community    schedule 31.01.2018
comment
Согласно docs.python.org/2/library/, shell = True может вызвать проблемы с безопасностью. - person Nick Predey; 20.03.2018
comment
@Nick Predley: отмечено, но shell = False не выполняет желаемую функцию. Какие конкретно проблемы безопасности и какие альтернативы? Пожалуйста, дайте мне знать как можно скорее: я не хочу публиковать что-либо, что может вызвать проблемы у всех, кто это просматривает. - person ; 21.03.2018
comment
Основное предупреждение содержится в документации, но этот вопрос объясняет его более подробно: stackoverflow.com/questions/3172470/ - person tripleee; 03.12.2018

Для использования subprocess в Python 3.5+ в Linux мне помогло следующее:

import subprocess

# subprocess.run() returns a completed process object that can be inspected
c = subprocess.run(["ls", "-ltrh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(c.stdout.decode('utf-8'))

Как упоминалось в документации, значения PIPE представляют собой последовательности байтов и для правильного отображения их следует рассмотреть возможность декодирования. Для более поздних версий Python text=True и encoding='utf-8' добавляются в kwargs subprocess.run() < / а>.

Результатом вышеупомянутого кода является:

total 113M
-rwxr-xr-x  1 farzad farzad  307 Jan 15  2018 vpnscript
-rwxrwxr-x  1 farzad farzad  204 Jan 15  2018 ex
drwxrwxr-x  4 farzad farzad 4.0K Jan 22  2018 scripts
.... # Some other lines
person Farzad Vertigo    schedule 29.01.2019

Вот вызов внешней команды и возврат или печать вывода команды:

Subprocess check_output в Python подходит для

Запустить команду с аргументами и вернуть ее вывод в виде байтовой строки.

import subprocess
proc = subprocess.check_output('ipconfig /all')
print proc
person Rajiv Sharma    schedule 11.10.2016
comment
Аргумент должен быть правильно токенизирован в список, или вы должны явно передать shell=True. В Python 3.x (где x ›3, я думаю) вы можете получить вывод как правильную строку с помощью universal_newlines=True, и вы, вероятно, захотите переключиться на subproces.run() - person tripleee; 03.12.2018

Если вам нужно вызвать команду оболочки из записной книжки Python (например, Jupyter, Zeppelin, Databricks , или Google Cloud Datalab) вы можете просто использовать префикс !.

Например,

!ls -ilF
person dportman    schedule 08.05.2018

Используйте subprocess.call:

from subprocess import call

# Using list
call(["echo", "Hello", "world"])

# Single string argument varies across platforms so better split it
call("echo Hello world".split(" "))
person andruso    schedule 12.04.2014

Если вы пишете сценарий оболочки Python и в вашей системе установлен IPython, вы можете использовать префикс bang для запуска команды оболочки внутри IPython:

!ls
filelist = !ls
person noɥʇʎԀʎzɐɹƆ    schedule 28.08.2019
comment
@PeterMortensen Я не думаю, что он работает в DOS, но он должен работать в Cygwin. - person noɥʇʎԀʎzɐɹƆ; 30.11.2019

Существует множество различных способов запуска внешних команд в Python, и все они имеют свои плюсы и минусы.

Мои коллеги и я пишем инструменты системного администрирования Python, поэтому нам нужно запускать множество внешних команд, и иногда вы хотите, чтобы они блокировались или выполнялись асинхронно, по тайм-ауту, обновлялись каждую секунду и т. Д.

Существуют также разные способы обработки кода возврата и ошибок, и вы можете захотеть проанализировать вывод и предоставить новый ввод (в ожидайте стиля). Или вам нужно будет перенаправить стандартный ввод, стандартный вывод и стандартная ошибка для запуска на другом tty (например, при использовании Экран GNU).

Так что вам, вероятно, придется написать много оболочек вокруг внешней команды. Итак, вот модуль Python, который мы написали, который может обрабатывать практически все, что вы хотите, а если нет, он очень гибкий, поэтому вы можете легко его расширить:

https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/run.py

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

person Jens Timmerman    schedule 17.04.2013

После некоторого исследования у меня есть следующий код, который мне очень подходит. Он в основном печатает как стандартный вывод, так и стандартную ошибку в реальном времени.

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result
person Jake W    schedule 14.03.2014
comment
ваш код может потерять данные, когда подпроцесс завершается, пока некоторые данные находятся в буфере. Вместо этого читайте до EOF, см. teed_call () - person jfs; 13.07.2015

Для Python 3.5+ рекомендуется использовать функцию из подпроцесса модуль. Это возвращает объект CompletedProcess, из которого вы можете легко получить выходные данные, а также код возврата.

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
person Chiel ten Brinke    schedule 17.03.2016
comment
ответ с функцией запуска был добавлен в 2015 году. Вы повторили это. Я думаю, это была причина голосования против - person Greg Eremeev; 11.03.2017

import subprocess

p = subprocess.run(["ls", "-ltr"], capture_output=True)
print(p.stdout.decode(), p.stderr.decode())

Попробовать в Интернете

person Vishal    schedule 09.10.2019
comment
Объяснение было бы в порядке. Например, в чем заключается идея и чем она отличается от предыдущих 50 ответов 11 лет спустя? - person Peter Mortensen; 07.04.2021
comment
Это идентично вашему собственному ответу, полученному несколькими днями ранее, только с еще меньшей детализацией. - person tripleee; 09.06.2021

Использование функции Popen модуля subprocess Python - это самый простой способ запуска команд Linux. В этом случае функция Popen.communicate() выдаст вывод ваших команд. Например

import subprocess

..
process = subprocess.Popen(..)   # Pass command and arguments to the function
stdout, stderr = process.communicate()   # Get command output and error
..
person Asif Hasnain    schedule 24.07.2015
comment
Это уже неверно, и, вероятно, не было, когда был опубликован этот ответ. Вам следует предпочесть subprocess.check_call() и друзей, если вам не нужен более низкий уровень управления более сложным Popen(). В последних версиях Python популярной рабочей лошадкой является subprocess.run() - person tripleee; 03.12.2018

Есть много способов вызвать команду.

  • Например:

если and.exe требуется два параметра. В cmd мы можем вызвать sample.exe, использовать это: and.exe 2 3 и отобразить 5 на экране.

Если мы используем сценарий Python для вызова and.exe, мы должны сделать что-то вроде ..

  1. os.system(cmd,...)

    • os.system(("and.exe" + " " + "2" + " " + "3"))
  2. os.popen(cmd,...)

    • os.popen(("and.exe" + " " + "2" + " " + "3"))
  3. subprocess.Popen(cmd,...)
    • subprocess.Popen(("and.exe" + " " + "2" + " " + "3"))

Это слишком сложно, поэтому мы можем объединить cmd с пробелом:

import os
cmd = " ".join(exename,parameters)
os.popen(cmd)
person liuyip    schedule 12.09.2016
comment
os.popen не следует больше рекомендовать и, возможно, даже упоминать. В примере subpocess аргументы следует передавать в виде списка, а не объединять их пробелами. - person tripleee; 03.12.2018

os.popen() - самый простой и безопасный способ выполнить команду. Вы можете выполнить любую команду, которую запускаете в командной строке. Кроме того, вы также сможете записывать вывод команды, используя os.popen().read()

Сделать это можно так:

import os
output = os.popen('Your Command Here').read()
print (output)

Пример, в котором вы перечисляете все файлы в текущем каталоге:

import os
output = os.popen('ls').read()
print (output)
# Outputs list of files in the directory
person Trect    schedule 26.11.2019

Обновление 2015: в Python 3.5 добавлен subprocess.run, который намного проще в использовании, чем старый API подпроцесса https://docs.python.org/3/library/subprocess.html#subprocess.run. Я рекомендую это.


модуль подпроцесса, описанный ранее от Eli очень эффективен, но синтаксис стандартный системный вызов и проверка его вывода излишне многословны.

Самый простой способ выполнить системный вызов - использовать модуль команд (только для Linux ).

> import commands
> commands.getstatusoutput("grep matter alice-in-wonderland.txt")
(0, "'Then it doesn't matter which way you go,' said the Cat.")

Первый элемент в кортеже - это код возврата процесса. Второй элемент - это стандартный вывод (и стандартная ошибка, объединенная).

Python 2.6 (2008 г.) отказался от модуля команд, но это не значит, что вы не должны его использовать. Только то, что они его больше не разрабатывают, и это нормально, потому что он уже совершенен (это небольшая, но важная функция).

person Colonel Panic    schedule 18.04.2013
comment
Устаревший не только означает, что он больше не разрабатывается, но и вам не рекомендуется его использовать. Устаревшие функции могут выйти из строя в любой момент, могут быть удалены в любое время или могут быть опасными. Вы никогда не должны использовать это в важном коде. Устаревание - это просто лучший способ, чем немедленное удаление функции, потому что это дает программистам время адаптироваться и заменить устаревшие функции. - person Misch; 19.04.2013
comment
Просто чтобы доказать свою точку зрения: устарело с версии 2.6: модуль команд был удален в Python 3. Вместо этого используйте модуль подпроцесса. - person Misch; 19.04.2013
comment
Это не опасно! Разработчики Python осторожны только в том, чтобы разрывать функции между основными выпусками (то есть между 2.x и 3.x). Я использую модуль команд с Python 2.4 2004 года. То же самое и сегодня работает в Python 2.7. - person Colonel Panic; 23.04.2013
comment
Под опасным я не имел в виду, что его можно удалить в любое время (это другая проблема), и я не говорил, что использовать этот конкретный модуль опасно. Однако это может стать опасным, если будет обнаружена уязвимость в системе безопасности, но модуль не будет развиваться и не поддерживается. (Я не хочу сказать, что этот модуль уязвим или не уязвим для проблем безопасности, просто говорю об устаревших вещах в целом) - person Misch; 23.04.2013

Python 3.5+

import subprocess

p = subprocess.run(["ls", "-ltr"], capture_output=True)
print(p.stdout.decode(), p.stderr.decode())

Попробовать в Интернете

person Vishal    schedule 03.10.2019

Если вы не используете пользовательский ввод в командах, вы можете использовать следующее:

from os import getcwd
from subprocess import check_output
from shlex import quote

def sh(command):
    return check_output(quote(command), shell=True, cwd=getcwd(), universal_newlines=True).strip()

И используйте его как

branch = sh('git rev-parse --abbrev-ref HEAD')

shell=True создаст оболочку, поэтому вы можете использовать канал и подобные оболочки sh('ps aux | grep python'). Это очень удобно для выполнения жестко запрограммированных команд и обработки их вывода. universal_lines=True гарантирует, что результат будет возвращен в виде строки, а не в двоичном формате.

cwd=getcwd() обеспечит выполнение команды в том же рабочем каталоге, что и интерпретатор. Это удобно для работы команд Git, как в приведенном выше примере имени ветки Git.

Некоторые рецепты

  • свободная память в мегабайтах: sh('free -m').split('\n')[1].split()[1]
  • свободное место на / в процентах sh('df -m /').split('\n')[1].split()[4][0:-1]
  • Загрузка процессора sum(map(float, sh('ps -ef -o pcpu').split('\n')[1:])

Но это небезопасно для ввода пользователем, из документации:

Соображения безопасности

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

При использовании shell = True функцию shlex.quote () можно использовать для правильного экранирования пробелов и метасимволов оболочки в строках, которые будут использоваться для создания команд оболочки.

Даже при использовании shlex.quote() полезно сохранять небольшую паранойю при использовании пользовательского ввода в командах оболочки. Один из вариантов - использовать жестко запрограммированную команду для получения общего вывода и фильтрации по вводу пользователя. В любом случае использование shell=False гарантирует, что будет выполнен только тот процесс, который вы хотите выполнить, иначе вы получите ошибку No such file or directory.

Также есть некоторое влияние на производительность shell=True, из моих тестов кажется, что он примерно на 20% медленнее, чем shell=False (по умолчанию).

In [50]: timeit("check_output('ls -l'.split(), universal_newlines=True)", number=1000, globals=globals())
Out[50]: 2.6801227919995654

In [51]: timeit("check_output('ls -l', universal_newlines=True, shell=True)", number=1000, globals=globals())
Out[51]: 3.243950183999914
person geckos    schedule 31.03.2019

Я бы порекомендовал следующий метод "запустить", и он поможет нам получить стандартный вывод, стандартная ошибка и статус выхода как словарь; вызывающий его может прочитать словарь, возвращаемый методом run, чтобы узнать фактическое состояние процесса.

  def run (cmd):
       print "+ DEBUG exec({0})".format(cmd)
       p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
       (out, err) = p.communicate()
       ret        = p.wait()
       out        = filter(None, out.split('\n'))
       err        = filter(None, err.split('\n'))
       ret        = True if ret == 0 else False
       return dict({'output': out, 'error': err, 'status': ret})
  #end
person Viswesn    schedule 28.04.2016
comment
Это не полностью переопределяет что-то вроде subprocess.run(). Вам следует особенно избегать shell=True, когда это не является строго необходимым. - person tripleee; 03.12.2018
comment
Для чего #end? - person Peter Mortensen; 07.04.2021

Существует несколько способов вызова внешней команды из Python. Есть несколько функций и модулей с хорошими вспомогательными функциями, которые могут упростить задачу. Но среди всех рекомендуется модуль subprocess.

import subprocess as s
s.call(["command.exe", "..."])

Функция вызова запустит внешний процесс, передаст некоторые аргументы командной строки и дождется его завершения. Когда он закончится, вы продолжите выполнение. Аргументы в функции call передаются по списку. Первым аргументом в списке является команда, обычно в форме исполняемого файла, а последующие аргументы в списке - все, что вы хотите передать.

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

В конце концов, после списка есть ряд необязательных параметров, один из которых - это оболочка, и если вы установите для оболочки значение true, ваша команда будет запущена, как если бы вы ввели ее в командной строке.

s.call(["command.exe", "..."], shell=True)

Это дает вам доступ к таким функциям, как конвейер, вы можете перенаправлять на файлы, вы можете одновременно вызывать несколько команд.

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

s.check_call(...)

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

Наконец, если вам нужен более жесткий контроль, Popen конструктор, который также принадлежит модулю subprocess. Он также принимает те же аргументы, что и функция incall и check_call, но возвращает объект, представляющий запущенный процесс.

p=s.Popen("...")

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

person Kashif Iftikhar    schedule 27.02.2020

Я написал оболочку для обработки ошибок, перенаправления вывода и прочего.

import shlex
import psutil
import subprocess

def call_cmd(cmd, stdout=sys.stdout, quiet=False, shell=False, raise_exceptions=True, use_shlex=True, timeout=None):
    """Exec command by command line like 'ln -ls "/var/log"'
    """
    if not quiet:
        print("Run %s", str(cmd))
    if use_shlex and isinstance(cmd, (str, unicode)):
        cmd = shlex.split(cmd)
    if timeout is None:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
        retcode = process.wait()
    else:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
        p = psutil.Process(process.pid)
        finish, alive = psutil.wait_procs([p], timeout)
        if len(alive) > 0:
            ps = p.children()
            ps.insert(0, p)
            print('waiting for timeout again due to child process check')
            finish, alive = psutil.wait_procs(ps, 0)
        if len(alive) > 0:
            print('process {} will be killed'.format([p.pid for p in alive]))
            for p in alive:
                p.kill()
            if raise_exceptions:
                print('External program timeout at {} {}'.format(timeout, cmd))
                raise CalledProcessTimeout(1, cmd)
        retcode = process.wait()
    if retcode and raise_exceptions:
        print("External program failed %s", str(cmd))
        raise subprocess.CalledProcessError(retcode, cmd)

Вы можете назвать это так:

cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
person Asav Patel    schedule 24.10.2017

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

from sultan.api import Sultan

with Sultan.load(sudo=True, hostname="myserver.com") as sultan:
  sultan.yum("install -y tree").run()
person Zach Valenta    schedule 01.07.2019
comment
Re Предоставляет некоторые тонкости: Вы можете уточнить? - person Peter Mortensen; 30.11.2019

Я использую это для Python 3.6+:

import subprocess
def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : result, exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()
    rc = process.wait()
    if rc != 0:
        print ("Error: failed to execute command: ", cmd)
        print (error.rstrip().decode("utf-8"))
    return result.rstrip().decode("utf-8"), serror.rstrip().decode("utf-8")
# def
person ivanmara    schedule 19.04.2020
comment
Не используйте set shell=True для запуска команд, он открывает программу для уязвимостей внедрения команд. Вы должны передать команду в виде списка с аргументами cmd=["/bin/echo", "hello word"]. docs.python.org/3/library/ - person user5994461; 19.04.2020