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

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

75 ответов

Решение

Посмотрите на модуль подпроцесса в стандартной библиотеке:

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

Преимущество подпроцесса по сравнению с системой состоит в том, что он более гибкий (вы можете получить stdout, stderr, "реальный" код состояния, лучшую обработку ошибок и т. Д.).

Официальная документация рекомендует модуль подпроцесса поверх альтернативной os.system():

Модуль подпроцесса предоставляет более мощные средства для запуска новых процессов и получения их результатов; использование этого модуля предпочтительнее, чем использование этой функции [ os.system() ].

Раздел " Замена старых функций модулем подпроцесса " в документации подпроцесса может иметь несколько полезных рецептов.

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

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

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

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

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

  3. 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. Смотрите документацию.

  4. call функция от subprocess модуль. Это в основном так же, как Popen class и принимает все те же аргументы, но он просто ждет завершения команды и выдает код возврата. Например:

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

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

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

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

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

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

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

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

Я обычно использую:

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(),

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

Предположим, что вы хотите запустить длинную задачу из 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 (win xp) родительский процесс не завершится, пока longtask.py не завершит свою работу. Это не то, что вы хотите в CGI-скрипте. Проблема не специфична для Python, в сообществе PHP проблемы одинаковы.

Решение состоит в том, чтобы передать DETACHED_PROCESS Флаг создания процесса в базовую функцию CreateProcess в win 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 пока не проливает свет.

import os
os.system("your command")

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

Я бы рекомендовал использовать модуль подпроцесса вместо os.system, потому что он делает экранирование для вас и поэтому намного безопаснее: http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost'])
import os
cmd = 'ls -al'
os.system(cmd)

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

Есть много разных библиотек, которые позволяют вам вызывать внешние команды с 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.system а также os.popen (Примечание. Существует также подпроцесс.popen). ОС всегда будет запускать оболочку и является простой альтернативой для людей, которые не нуждаются или не знают, как использовать subprocess.run,

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

ш

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

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

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # 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 это лучшая альтернатива.

Редактирование было основано на комментарии Дж. Ф. Себастьяна.

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

Модуль использования подпроцесса (Python 3):

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

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

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

ProTip: 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,

Я всегда использую 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)

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

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

child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

child.expect('(?i)password')

Если вам нужен вывод команды, которую вы вызываете, вы можете использовать subprocess.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'

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

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

Обновить:

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')

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

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

Пример использования из 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'>]

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

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()

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

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

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

Зачем?

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

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

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

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> 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:

>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(Мне кажется интересным и немного нелогичным, что информация о версии помещается в stderr вместо stdout.)

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

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

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\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 будет повторно вызвано после завершения дочернего процесса.

Если проверка имеет значение true, и процесс завершается с ненулевым кодом завершения, будет вызвано исключение 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=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

Но более информативным является 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=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

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

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

https://docs.python.org/2/library/subprocess.html

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

import os
os.system('cat testfile')

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


TL; DR в 2020 году

Большое преимущество 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 "stackru-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, с которыми вы можете легко работать.

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

Сделать, если result.returncode == 127: print("Программа не удалась по какой-то странной причине") elif result.returncode == 0: print("Программа завершилась успешно") else: print("Программа неожиданно завершилась неудачно")

Если вы просто хотите проверить, удалась ли программа (код возврата == 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; обновите его до самого последнего доступного. В противном случае в этом сообщении Stackru есть другие ответы, показывающие вам более старые альтернативные решения.

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

Получите больше информации здесь.

Есть также Пламбум

>>> 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

Без вывода результата:

import os
os.system("your command here")

С выводом результата:

import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")

Использование:

import os

cmd = 'ls -al'

os.system(cmd)

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

Для более os функции, вот документация.

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

import os
cmd = "your command"
os.system(cmd)

Мне очень нравится shell_command за его простоту. Он построен поверх модуля подпроцесса.

Вот пример из документации:

>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py  shell_command.py  test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0

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

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

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

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

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

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

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

Я склонен использовать подпроцесс вместе с 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)

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

Бесстыдный плагин, я для этого написал библиотеку: P https://github.com/houqp/shell.py

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

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

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

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

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

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

Заметки о диспетчере задач (ts):

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

    ts -S <number-of-slots>

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

Другие вопросы по тегам