Язык программирования Python

subprocess – создание и взаимодействие с процессами в Python

Стандартный модуль subprocess позволяет вызывать процессы из Python и взаимодействовать с ними: отправлять данные на вход (stdin) и получать информацию на выходе (stdout).

Также можно дождаться завершения процесса или завершить его преждевременно и получить возвращаемое значение.

Это идеальный и рекомендуемый метод для выполнения команд операционной системы или запуска программ (вместо традиционного os.system()) и опционального взаимодействия с ними.

Самый простой способ выполнить команду или вызвать процесс – это функция call() (с Python 2.4 по 3.4) или run() (3.5+).

Например, следующий код выполняет команду, которая перезагружает систему.

Python 3.5+

>>> import subprocess >>> subprocess.run(["shutdown", "-r"])
Code language: CSS (css)

Python 2.4-3.4

>>> import subprocess >>> subprocess.call(["shutdown", "-r"])
Code language: CSS (css)

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

Python 3.5+

>>> subprocess.run("shutdown -r") Traceback (most recent call last): ... OSError: [Errno 2] No such file or directory
Code language: CSS (css)

Python 2.4-3.4

>>> subprocess.call("shutdown -r") Traceback (most recent call last): ... OSError: [Errno 2] No such file or directory
Code language: CSS (css)

Обе функции не возвращаются, пока вызванная программа не завершится. call() вернет возвращаемое значение выполненной команды или программы в виде целого числа. run() вернет экземпляр CompletedProcess, который содержит атрибут returncode.

Python 3.5+

>>> p = subprocess.run(["python", "--version"]) Python 3.5.1 >>> p.returncode 0
Code language: JavaScript (javascript)

Python 2.4-3.4

>>> ret = subprocess.call(["python", "--version"]) Python 2.7.13 >>> ret 0
Code language: JavaScript (javascript)

(Обычно 0 означает, что программа была выполнена правильно).

Для использования команд терминала (таких как clear или cls для очистки консоли, cd для перемещения по дереву каталогов и т.д.) необходимо указать параметр shell=True.

Python 3.5+

>>> subprocess.run("cls", shell=True)
Code language: PHP (php)

Python 2.4-3.4

>>> subprocess.call("cls", shell=True)
Code language: PHP (php)

Важно отметить, что использование shell=True является потенциальной уязвимостью, если команда выполняется пользователем (аналогично методу инъекции SQL-кода в приложениях, взаимодействующих с базами данных).

Теперь, чтобы сохранить вывод команды в виде строки Python, мы должны указать параметры stdout и stderr. Например:

Python 3.5+

>>> p = subprocess.run("ver", stdout=subprocess.PIPE, shell=True) >>> p.stdout b'\r\nMicrosoft Windows [Versi\xa2n 6.2.9200]\r\n'
Code language: PHP (php)

Python 2.4-3.4

>>> p = subprocess.Popen("ver", stdout=subprocess.PIPE, shell=True) >>> stdout = p.communicate()[0] >>> stdout '\r\nMicrosoft Windows [Versi\xa2n 6.2.9200]\r\n'
Code language: PHP (php)

Команда Windows ver отправляет версию системы в stdout. Мы можем получить к нему доступ через атрибут stdout (3.5+) или метод communicate() (2.4-3.4)

Обратите внимание, что в Python 3 результат является экземпляром типа bytes, в Python 2 – типа str.

Для доступа к потенциальным ошибкам, отправленным в stderr, процесс аналогичен:

Python 3.5+

>>> p = subprocess.run(["python", "-m", "inexistente"], stderr=subprocess.PIPE) >>> p.stderr b'C:\\python35\\python.exe: No module named inexistente\r\n'
Code language: JavaScript (javascript)

Python 2.4-3.4

>>> p = subprocess.Popen(["python", "-m", "inexistente"], stderr=subprocess.PIPE) >>> stderr = p.communicate()[1] >>> stderr 'C:\\Python27\\python.exe: No module named inexistente\r\n'
Code language: JavaScript (javascript)

И stdout, и stderr опционально принимают файлы для хранения данных на диске:

Python 3.5+

with open("errores.log", "w") as f: p = subprocess.run(["python", "-m", "inexistente"], stderr=f)
Code language: JavaScript (javascript)

Python 2.4-3.4

with open("errores.log", "w") as f: p = subprocess.Popen(["python", "-m", "inexistente"], stderr=f)
Code language: JavaScript (javascript)

Также можно перенаправить все, что отправлено в stderr, в stdout:

Python 3.5+

>>> p = subprocess.run(["python", "-m", "inexistente"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) >>> p.stdout b'C:\\python35\\python.exe: No module named inexistente\r\n'
Code language: JavaScript (javascript)

Python 2.4-3.4

>>> p = subprocess.Popen(["python", "-m", "inexistente"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) >>> stdout = p.communicate()[0] >>> stdout 'C:\\Python27\\python.exe: No module named inexistente\r\n'
Code language: JavaScript (javascript)

Чтобы отправить данные на вход (stdin), давайте сначала рассмотрим следующий пример кода:

#!/usr/bin/env python # -*- coding: utf-8 -*- try: # Python 2. name = raw_input("Имя: ") except NameError: # Python 3. name = input("Имя: ") print("Привет " + name)
Code language: PHP (php)

Этот небольшой код, назовем его program.py, предлагает пользователю ввести свое имя, а затем выводит на экран приветствие.

Через подпроцесс мы можем вызвать его, программно ввести имя и получить приветствие в виде строки Python.

Python 3.5+

p = subprocess.run(["python", "program.py"], input=b"Иван", stdout=subprocess.PIPE) print(p.stdout)
Code language: PHP (php)

Python 2.4-3.4

p = subprocess.Popen(["python", "program.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdout = p.communicate(input="Иван")[0] print stdout
Code language: PHP (php)

Имя передается через входной параметр (из функций run() или communicate() в зависимости от версии) на вход (stdin), а приветствие получается путем обращения к содержимому выхода (stdout).

Другие допустимые аргументы для popen(), call() и run() включают cwd (текущий рабочий каталог), который указывает место, где будет выполняться команда или программа.

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

Python 3.5+

>>> subprocess.run("ls", cwd="Desktop")
Code language: JavaScript (javascript)

Python 2.4-3.4

>>> subprocess.call("ls", cwd="Desktop")
Code language: JavaScript (javascript)

Экземпляры Popen() включают методы terminate() и kill(), чтобы завершить или убить процесс, соответственно.

Дистрибутивы Linux различают сигналы SIGTERM и SIGKILL. В Windows нет никакой разницы между этими двумя функциями.

# Преждевременное прекращение процесса. p = subprocess.Popen(["python", "--version"]) p.terminate()
Code language: PHP (php)

Другие методы включают p.wait() для блокировки выполнения до тех пор, пока программа не завершится (это происходит по умолчанию при вызове call() или run()) и атрибут p.pid, который хранит идентификатор созданного процесса.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *