Сообщить об ошибке.

Класс Popen() модуля subprocess в Python

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

Синтаксис:

import subprocess

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=(), *, \
                 encoding=None, errors=None, text=None)

Параметры:

  • args - список или строка, запускаемая программа с аргументами,
  • bufsize=-1 - буферизация,
  • executable=None - замещающая программа для выполнения,
  • stdin=None - поток данных, отправляемых в процесс,
  • stdout=None - поток вывода программы,
  • stderr=None - поток ошибок программы,
  • preexec_fn=None - пользовательская функция, выполняемая до запуска программы,
  • close_fds=True - управляет файловыми дескрипторами,
  • shell=False - True, если программа и ее аргументы представлены как одна строка,
  • cwd=None - путь к рабочему каталогу запускаемой программы,
  • env=None - переменные среды для нового процесса,
  • universal_newlines=None - тоже, что и параметр text,
  • startupinfo=None - объект subprocess.STARTUPINFO,
  • creationflags=None - один или несколько констант Windows,
  • restore_signals=True - сигналы восстанавливаются до SIG_DFL,
  • start_new_session=False - управляет системным вызов setsid(),
  • pass_fds=() - последовательность файловых дескрипторов,
  • encoding=None - кодировка, если text=True,
  • errors=None - обработчик ошибок кодировки,
  • text=None - текстовый режим для stdin, stdout и stderr.

Возвращаемое значение:

Описание:

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

Аргументы args должны быть последовательностью программных аргументов или же одиночной строкой или объектом, похожим на путь. По умолчанию, если args - список, то исполняемая программа является первым элементом в args. Если args является строкой, интерпретация зависит от платформы и описана ниже. Если не указано иное, рекомендуется передавать аргументы в виде последовательности.

Пример передачи некоторых аргументов во внешнюю программу в виде последовательности:

import subprocess
subprocess.Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])

По умолчанию в Unix, если args является строкой, то она интерпретируется как имя исполняемой программы или путь к ней БЕЗ аргументов.

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

>>> import shlex, subprocess, pprint
>>> cmd = '/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo \'$MONEY\'"'
>>> args = shlex.split(cmd)
>>> pprint.pprint(args, width='60')
#['/bin/vikings',
# '-input',
# 'eggs.txt',
# '-output',
# 'spam spam.txt',
# '-cmd',
# "echo '$MONEY'"]
>>> p = subprocess.Popen(args)

В Windows, если параметр args является последовательностью, то он будет преобразован в строку, так как базовый CreateProcess() в Windows работает со строками.

Аргумент shell (по умолчанию False) указывает, использовать ли оболочку в качестве программы для выполнения. Если shell имеет значение True, рекомендуется передавать аргументы как строку, а не как последовательность.

В Unix с аргументом shell=True оболочкой по умолчанию является /bin/sh, при этом параметр args должен быть строкой, которая определяет команду со всеми ее аргументами для выполнения через эту оболочку. Это означает, что команда должна быть отформатирована точно так же, как при вводе в командной строке. Форматирование включает кавычки или обратную косую черту, экранирующие имена файлов с пробелами в них. Подробнее в разделе "Часто используемые параметры модуля subprocess".

Если параметр args это последовательность при установленном shell=True, то первый элемент задает командную строку, а элементы args будут рассматриваться как дополнительные аргументы самой оболочки. То есть subprocess.Popen() делает эквивалент:

subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])

В Windows с shell=True переменная среды COMSPEC определяет оболочку по умолчанию. В Windows требуется устанавливать аргумент shell=True только тогда, когда необходимо выполнить команду, встроенную в оболочку, например dir или copy. Не нужно устанавливать shell=True для запуска командного файла .bat или консольного исполняемого файла .exe.

Аргумент bufsize будет передаваться в качестве соответствующего аргумента функции open() при создании файловых объектов stdin, stdout и stderr:

  • 0 означает небуферизованный, чтение и запись являются одним системным вызовом и могут возвращать short.
  • 1 означает строку с буферизацией, используется только если universal_newlines=True, т. е. в текстовом режиме.
  • Любое другое положительное значение означает использование буфера примерно такого размера.
  • Отрицательный bufsize (по умолчанию) означает, что будет использоваться системное значение по умолчанию io.DEFAULT_BUFFER_SIZE.

Аргумент executable указывает замещающую программу для выполнения. Это нужно очень редко. Когда параметр shell=False, то executable заменяет программу для выполнения, заданную в args. Тем не менее, оригинальные args все еще передаются в программу. В Unix, имя args становится отображаемым именем исполняемого файла в таких утилитах, как ps.

# произойдет замена интерпретатора `python2` на `python3`
subprocess.Popen(['python', 'test.py'], executable='python3')

Если в Unix параметр shell=True, то аргумент executable должен указывать оболочку для замены по умолчанию /bin/sh, при этом параметр args должен быть строкой, которая определяет команду со всеми ее аргументами для выполнения через новую оболочку.

# выполнит /bin/bash python3 test.py
subprocess.Popen('python3 test.py', executable='/bin/bash', shell=True)

Аргументы stdin, stdout и stderr задают стандартный обработчик входных данных, стандартный вывод и стандартные файл ошибок соответственно. Допустимые значения: subprocess.PIPE - указывает, что должна быть создана новый поток для дочернего элемента. subprocess.DEVNULL указывает, что будет использоваться специальный файл os.devnull. При настройках по умолчанию None перенаправление не происходит. Дескрипторы файла дочернего процесса будут унаследованы от родителя. Кроме того параметр stderr может принимать subprocess.STDOUT, что означает, что данные stderr из дочернего процесса должны быть записаны в тот же дескриптор файла, что и для stdout.

import subprocess
# команда bash '$ dmesg | grep hda' при помощи `stdin` и `stdout`
>>> p1 = subprocess.Popen(["dmesg"], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(["grep", "hda"], stdin=p1.stdout, stdout=subprocess.PIPE)
# Разрешить p1 для получения `SIGPIPE`, если p2 выходит.
>>> p1.stdout.close()
>>> output = p2.communicate()[0]
# или то же самое, но shell=True
>>> p = subprocess.Popen('dmesg | grep hda', shell=True, stdout=subprocess.PIPE)

Если установлен аргумент preexec_fn, то этот объект будет вызываться в дочернем процессе непосредственно перед выполнением программы. Доступно только Unix.

# Перед вызовом процесса меняем его UID
# ! нужны соответствующие права
subprocess.Popen(['id'], preexec_fn=os.setuid(1000))

Предупреждение.

  • Параметр preexec_fn небезопасен для использования при наличии потоков в приложении. Дочерний процесс может заблокироваться до вызова exec. Если все таки preexec_fn используется, то функция должна быть крайне простой и с минимальным количеством вызываемых библиотек.
  • В Python-3.8 и выше параметр preexec_fn больше не поддерживается в субинтерпретаторах. Использование параметра в субинтерпретаторе вызывает исключение RuntimeError.

Примечание.

  • Если необходимо изменить окружение для дочернего процесса, то используйте параметр env вместо того, чтобы делать это в preexec_fn.
  • Аргумент start_new_session может заменить ранее распространенное использование параметра preexec_fn для вызова os.setsid() дочернего процесса.

Если аргумент close_fds имеет значение True, то все файловые дескрипторы, кроме 0, 1 и 2 будут закрыты до выполнения дочернего процесса. В противном случае, когда close_fds имеет значение False, файловые дескрипторы подчиняются своему наследуемому флагу, как описано в разделе "Наследование файловых дескрипторов".

В Windows, если close_fds имеет значение True, тогда никакие дескрипторы не будут наследоваться дочерним процессом, если это явно не передано в элемент handle_list в STARTUPINFO.lpAttributeList или при стандартном перенаправлении дескриптора.

В Python-3.7 и выше в Windows значение по умолчанию для close_fds было изменено с False на True при перенаправлении стандартных дескрипторов.

Аргумент pass_fds - это необязательная последовательность файловых дескрипторов, которые остаются открытыми между родителем и потомком. Предоставление любого pass_fds заставляет close_fds быть True. Доступно только Unix.

Если аргумент cwd не равен None, то subprocess.Popen() меняет рабочий каталог на cwd перед выполнением дочернего процесса. Параметр cwd может быть строкой и path-like объектом. В частности, если путь исполняемого файла является относительным путем, то Popen() ищет исполняемый файл или первый элемент в args относительно пути cwd.

Если для параметра restore_signals=True (по умолчанию), то все сигналы, которые Python установил для SIG_IGN, восстанавливаются до SIG_DFL в дочернем процессе до выполнения exec. В настоящее время это включает сигналы SIGPIPE, SIGXFZ и SIGXFSZ. Доступно только Unix.

Если аргумент start_new_session имеет значение True, то системный вызов setsid() будет сделан в дочернем процессе до начала запуска программы. Доступно только Unix.

Если аргумент env не равен None, то это должен быть словарь, которое определяет переменные среды для нового процесса. Они используются вместо поведения по умолчанию - наследования среды текущего процесса.

# запуск Python скрипта из другого виртуального окружения
env = os.environ.copy()
env['PATH'] = '/path/to/env/bin'
child=subprocess.Popen(['/path/to/env/bin/python3', '/path/to/env/test.py'], env=env)

Если указаны кодировка encoding или errors или аргумент text имеет значение True, то файловые объекты для stdin, stdout и stderr открываются в текстовом режиме с использованием указанной кодировки и обработчика ошибок, как описано разделе "Часто используемые аргументы".

Аргумент universal_newlines эквивалентен параметру text и предназначен для обратной совместимости. По умолчанию файловые объекты открываются в бинарном режиме.

Если задан аргумент startupinfo, то это будет объектом subprocess.STARTUPINFO, который передается в базовую функцию CreateProcess.

Если задан сreationflags, то он может быть одним или несколькими из констант Windows.

Popen-объекты поддерживаются контекстные менеджеры с помощью оператора with: при выходе стандартные файловые дескрипторы закрываются.

with Popen(["ifconfig"], stdout=PIPE) as proc:
    log.write(proc.stdout.read())