Как выполнять команды оболочки в Python с помощью метода запуска подпроцесса

How Execute Shell Commands Python Using Subprocess Run Method



Подпроцесс - это встроенный модуль Python, который можно использовать для создания новых процессов и взаимодействия с их потоками входных и выходных данных. Проще говоря, вы можете использовать его для выполнения команд оболочки и исполняемых двоичных файлов, обычно разбросанных по различным папкам bin в файловой системе Linux. Вы также можете указать полный путь к исполняемому двоичному файлу и использовать любые параметры командной строки, связанные с двоичным файлом. В этой статье объясняется, как использовать модуль подпроцесса и его метод запуска в приложениях Python. Все примеры кода в статье протестированы с Python 3.8.2 в Ubuntu 20.04.

Метод Subprocess.run

Метод Subprocess.run принимает список аргументов. Когда метод вызывается, он выполняет команду и ожидает завершения процесса, возвращая в конце объект CompletedProcess. Объект CompletedProcess возвращает stdout, stderr, исходные аргументы, использованные при вызове метода, и код возврата. Stdout относится к потоку данных, создаваемому командой, а stderr относится к любым ошибкам, возникающим во время выполнения программы. Любой ненулевой код возврата (код выхода) будет означать ошибку при выполнении команды в методе subprocess.run.







Пример 1: Вывод содержимого текстового файла с помощью метода Subprocess.run

Приведенная ниже команда выведет содержимое файла data.txt при условии, что он содержит строку name = John.



Импортировать подпроцесс
подпроцесс.запустить(['Кот', 'data.txt'])

Выполнение приведенного выше кода вернет следующий результат:



имязнак равноДжон
ЗавершенныйПроцесс(аргументызнак равно['Кот', 'data.txt'],код возвратазнак равно0)

Первый элемент аргумента списка - это имя выполняемой команды. Любой элемент в списке, следующий за первым элементом, считается параметрами или переключателями командной строки. Вы также можете использовать одинарное тире и двойное тире для определения параметров. Например, чтобы перечислить файлы и папки в каталоге, код будет выглядеть следующим образом: subprocess.run ([ls, -l]. В большинстве этих случаев вы можете рассматривать любой аргумент, разделенный пробелами в команде оболочки, как отдельный элемент в список, предоставленный методу subprocess.run.





Пример 2: Подавить вывод метода Subprocess.run

Чтобы подавить вывод метода subprocess.run, вам нужно будет предоставить stdout = subprocess.DEVNULL и stderr = subprocess.DEVNULL в качестве дополнительных аргументов.

Импортировать подпроцесс

подпроцесс.запустить(['Кот', 'data.txt'],стандартный выводзнак равноподпроцесс.DEVNULL,
stderrзнак равноподпроцесс.DEVNULL)

Выполнение приведенного выше кода приведет к следующему результату:



CompletedProcess (args = ['cat', 'data.txt'], returncode = 0)

Пример 3: захват вывода метода Subprocess.run

Чтобы захватить вывод метода subprocess.run, используйте дополнительный аргумент с именем capture_output = True.

Импортировать подпроцесс
выходзнак равно подпроцесс.запустить(['Кот', 'data.txt'],capture_outputзнак равноПравда)
Распечатать (выход)

Выполнение приведенного выше кода приведет к следующему результату:

ЗавершенныйПроцесс(аргументызнак равно['Кот', 'data.txt'],код возвратазнак равно0,
стандартный выводзнак равноб'name = Джон п',stderrзнак равноб'')

Вы можете получить индивидуальный доступ к значениям stdout и stderr, используя методы output.stdout и output.stderr. На выходе получается последовательность байтов. Чтобы получить строку в качестве вывода, используйте метод output.stdout.decode (utf-8). Вы также можете указать text = True в качестве дополнительного аргумента для вызова subprocess.run, чтобы получить вывод в строковом формате. Чтобы получить код статуса выхода, вы можете использовать метод output.returncode.

Пример 4: Исключение при сбое команды, выполненной методом Subprocess.run

Чтобы вызвать исключение, когда команда завершается с ненулевым статусом, используйте аргумент check = True.

Импортировать подпроцесс
подпроцесс.запустить(['Кот', 'data.tx'],capture_outputзнак равноПравда,текстзнак равноПравда,проверитьзнак равноПравда)

Выполнение приведенного выше кода приведет к следующему результату:

поднять CalledProcessError (retcode, process.args,
subprocess.CalledProcessError: Команда '[' cat ',' data.tx ']'
возвратил ненулевой статус выхода 1.

Пример 5: Передача строки команде, выполняемой методом Subprocess.run

Вы можете передать строку команде, которая будет выполняться методом subprocess.run, используя аргумент input = ’string’.

Импортировать подпроцесс
выходзнак равно подпроцесс.запустить(['Кот'], Входзнак равно'data.txt',capture_outputзнак равноПравда,
текстзнак равноПравда,проверитьзнак равноПравда)
Распечатать (выход)

Выполнение приведенного выше кода приведет к следующему результату:

CompletedProcess (args = ['cat'], returncode = 0, stdout = 'data.txt', stderr = '')

Как видите, приведенный выше код передает data.txt как строку, а не как файловый объект. Чтобы передать data.txt в виде файла, используйте аргумент stdin.

с участием открытым('data.txt') в качествеf:
выходзнак равно подпроцесс.запустить(['Кот'],стандартный вводзнак равнож,capture_outputзнак равноПравда,
текстзнак равноПравда,проверитьзнак равноПравда)
Распечатать (выход)

Выполнение приведенного выше кода приведет к следующему результату:

CompletedProcess (args = ['cat'], returncode = 0, stdout = 'name = John n', stderr = '')

Пример 6: Выполнение команды непосредственно в оболочке с помощью метода Subprocess.run

Можно запустить команду прямо в оболочке как есть, вместо использования разделения строк в основной команде и следующих за ней параметрах. Для этого вы должны передать shell = True в качестве дополнительного аргумента. Однако разработчики python не одобряют этого, поскольку использование shell = True может привести к проблемам с безопасностью. Вы можете узнать больше о последствиях для безопасности из здесь .

Импортировать подпроцесс
подпроцесс.запустить('cat' data.txt '',оболочказнак равноПравда)

Выполнение приведенного выше кода приведет к следующему результату:

name = Джон

Заключение

Метод subprocess.run в Python довольно мощный, поскольку он позволяет запускать команды оболочки внутри самого Python. Это помогает ограничить весь код самим Python без необходимости иметь дополнительный код сценария оболочки в отдельных файлах. Однако может быть довольно сложно правильно разметить команды оболочки в списке Python. Вы можете использовать метод shlex.split () для токенизации простых команд оболочки, но в длинных сложных командах - особенно с символами вертикальной черты - shlex не может правильно разделить команду. В таких случаях отладка может оказаться сложной задачей. Вы можете использовать аргумент shell = True, чтобы избежать этого, но есть определенные проблемы безопасности, связанные с этим действием.