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

Использование модуля subprocess

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

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

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
  • args: Указывает команду, которую нужно выполнить. Это должна быть строка или список строковых параметров.
  • stdin, stdout и stderr: стандартные потоки ввода, вывода и ошибок дочернего процесса. Их значения могут быть subprocess.PIPE, subprocess.DEVNULL, существующим файловым дескриптором, уже открытым файловым объектом или None. subprocess.PIPE означает создание нового канала для дочернего процесса. subprocess.DEVNULL означает использование os.devnull. По умолчанию используется None, что означает, что ничего не делается. Кроме того, stderr можно объединить с stdout для совместного вывода.
  • timeout: Задает время ожидания команды. Если время выполнения команды превышает тайм-аут, дочерний процесс будет завершен, и будет вызвано исключение TimeoutExpired.
  • check: Если этот параметр установлен в True и код статуса завершения процесса не равен 0, будет вызвано исключение CalledProcessError.
  • encoding: Если этот параметр указан, stdin, stdout и stderr могут принимать строковые данные и кодировать их с использованием этой кодировки. В противном случае принимаются только данные типа bytes.
  • shell: Если этот параметр имеет значение True, указанная команда будет выполнена через оболочку операционной системы.

Вызов метода run возвращает экземпляр CompletedProcess. Он похож на прямое использование Popen; реализация такая же. Фактически он также вызывает Popen и примерно такой же, как конструктор Popen, например:

Пример

#Выполнить команду ls -l /dev/null
>>> subprocess.run(["ls", "-l", "/dev/null"])
crw-rw-rw-  1 root wheel    3,   2  5  4 13:34 /dev/null
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0)

returncode: Статус выполненного дочернего процесса. Обычно код возврата 0 указывает, что он завершил работу. Если значение отрицательное '-N', это указывает, что дочерний процесс был завершен.

Простой пример:

Пример

import subprocess
def runcmd(command):
    ret = subprocess.run(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8",timeout=1)
    if ret.returncode == 0:
        print("success:",ret)
    else:
        print("error:",ret)


runcmd(["dir","/b"])#Аргумент-последовательность
runcmd("exit 1")#Аргумент-строка

Результат вывода следующий:

success: CompletedProcess(args=['dir', '/b'], returncode=0, stdout='test.py\n', stderr='')
error: CompletedProcess(args='exit 1', returncode=1, stdout='', stderr='')

Popen() метод

Popen — это ядро subprocess; создание и управление дочерними процессами осуществляется через него.

Конструктор:

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

Общие параметры:

  • args: команда оболочки, которая может быть строкой или типом последовательности (например, list, tuple)
  • bufsize: Размер буфера. Используется при создании объектов канала для стандартных потоков. По умолчанию -1.
    0: Без буферизации
    1: Построчная буферизация, доступна только при universal_newlines=True, то есть в текстовом режиме
    Положительное число: Указывает размер буфера
    Отрицательное число: Указывает использовать системный размер буфера по умолчанию.
  • stdin, stdout, stderr: Соответственно представляют стандартные дескрипторы ввода, вывода и ошибок программы
  • preexec_fn: Действует только на платформах Unix. Используется для указания вызываемого объекта, который будет вызван перед запуском дочернего процесса.
  • shell: Если этот параметр имеет значение True, указанная команда будет выполнена через оболочку операционной системы.
  • cwd: Используется для установки текущего каталога дочернего процесса.
  • env: Используется для указания переменных среды дочернего процесса. Если env=None, переменные среды дочернего процесса будут унаследованы от родительского процесса.

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

Пример

>>> import subprocess
>>> p = subprocess.Popen('ls -l', shell=True)
>>> total 164
-rw-r--r--  1 root root   133 июл  4 16:25 admin-openrc.sh
-rw-r--r--  1 root root   268 Июл 10 15:55 admin-openrc-v3.sh
...
>>> p.returncode
>>> p.ожидание()
0
>>> p.returncode

Вы также можете использоватьp = subprocess.Popen(['ls', '-cl'])для создания дочернего процесса.

Методы объекта Popen

  • poll(): Проверяет, завершился ли процесс. Если завершился, возвращает returncode; в противном случае возвращает None.
  • wait(timeout): Ожидает завершения дочернего процесса.
  • communicate(input,timeout): Взаимодействует с дочерним процессом, отправляя и читая данные.
  • send_signal(signal): Отправляет сигнал дочернему процессу.
  • terminate(): Останавливает дочерний процесс, то есть отправляет сигнал SIGTERM дочернему процессу.
  • kill(): Уничтожает дочерний процесс. Отправляет сигнал SIGKILL дочернему процессу.

Пример

import time
import subprocess

def cmd(command):
    subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
    subp.wait(2)
    if subp.poll() == 0:
        print(subp.communicate()[1])
    else:
        print("Ошибка")



cmd("java -version")
cmd("exit 1")

Результат вывода следующий:

java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

失败

Справочная статья:

https://blog.csdn.net/weixin_42547344/article/details/80894760

https://blog.csdn.net/maosijunzi/article/details/80138458