subprocess — Управление подпроцессами


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

os.system
os.spawn*

Информацию о том, как модуль subprocess можно использовать для замены данных модулей и функций, можно найти в следующих разделах.

См.также

PEP 324 — PEP предлагающий модуль subprocess

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

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

Функция run() была добавлена в Python 3.5; если вам нужно сохранить совместимость со старыми версиями, см. раздел Старый высокоуровневый API.

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, **other_popen_kwargs)

Выполнить команду, описанную в args. Дождаться завершения команды, затем вернуть экземпляр CompletedProcess.

Аргументы, показанные выше, являются просто наиболее распространенными, описанными ниже в Часто используемые аргументы (отсюда и использование только ключевой нотации в сокращенной сигнатуре). Полная сигнатура функции во многом такая же, как у конструктора Popen — большинство аргументов функции передаются через данный интерфейс. (timeout, input, check и capture_output не являются.)

Если capture_output истинно, будут захвачены stdout и stderr. При использовании внутреннего объекта Popen автоматически создаётся с stdout=PIPE и stderr=PIPE. Аргументы stdout и stderr нельзя указывать одновременно с capture_output. Если вы хотите захватить и объединить оба потока в один, используйте stdout=PIPE и stderr=STDOUT вместо capture_output.

Аргумент timeout передаётся в Popen.communicate(). Если таймаут истечёт, дочерний процесс будет убит и будет ждать. Исключение TimeoutExpired будет повторно вызвано после завершения дочернего процесса.

Аргумент input передаётся в Popen.communicate() и, следовательно, в stdin подпроцесса. Если используется, это последовательность байтов, или строка (если указано encoding или errors), или истинный text. При использовании внутренний объект Popen автоматически создаётся с stdin=PIPE, и аргумент stdin также не может использоваться.

Если check истинно, и процесс завершается с ненулевым кодом выхода, возникает исключение CalledProcessError. Атрибуты этого исключения содержат аргументы, код выхода и stdout и stderr, если они были захвачены.

Если указаны encoding или errors или text истинно, файловые объекты для stdin, stdout и stderr открываются в текстовом режиме с использованием указанных encoding и errors или io.TextIOWrapper по умолчанию. Аргумент universal_newlines эквивалентен text и предоставляется для обратной совместимости. По умолчанию файловые объекты открываются в двоичном режиме.

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

Примеры:

>>> subprocess.run(["ls", "-l"])  # не захватывает вывод
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"], capture_output=True)
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', stderr=b'')

Добавлено в версии 3.5.

Изменено в версии 3.6: Добавлены параметры encoding и errors

Изменено в версии 3.7: Добавлен параметр text, как более понятный псевдоним universal_newlines. Добавлен параметр capture_output.

class subprocess.CompletedProcess

Возвращаемое значение из run(), представляющее завершённый процесс.

args

Аргументы, используемые для запуска процесса. Может быть списком или строкой.

returncode

Статус выхода из дочернего процесса. Как правило, статус выхода 0 указывает на успешное выполнение.

Отрицательное значение -N указывает, что дочерний был прерван сигналом N (только POSIX).

stdout

Захваченный стандартный вывод дочернего процесса. Последовательность байтов или строка, если run() была вызвана с encoding, errors или text=True. None, если стандартный вывод не был захвачен.

Если вы запустили процесс с stderr=subprocess.STDOUT, stdout и stderr будут объединены в этом атрибуте, а stderr будет None.

stderr

Захваченный stderr из дочернего процесса. Последовательность байтов или строка, если run() был вызван с кодировкой, ошибками или текстом = True. None, если stderr не был захвачен.

check_returncode()

Если returncode не равно нулю, вызывает CalledProcessError.

Добавлено в версии 3.5.

subprocess.DEVNULL

Специальное значение, которое может использоваться в качестве аргумента stdin, stdout или stderr для Popen и указывает, что будет использоваться специальный файл os.devnull.

Добавлено в версии 3.3.

subprocess.PIPE

Специальное значение, которое может использоваться в качестве аргумента stdin, stdout или stderr для Popen и указывает, что должен быть открыт конвейер (pipe) к стандартному потоку. Наиболее полезно с Popen.communicate().

subprocess.STDOUT

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

exception subprocess.SubprocessError

Базовый класс для всех остальных исключений из данного модуля.

Добавлено в версии 3.3.

exception subprocess.TimeoutExpired

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

cmd

Команда, которая использовалась для создания дочернего процесса.

timeout

Тайм-аут в секундах.

output

Вывод дочернего процесса, если он был захвачен run() или check_output(). В противном случае None.

stdout

Псевдоним для вывода для симметрии с stderr.

stderr

Выходные данные Stderr дочернего процесса, если они были захвачены run(). В противном случае None.

Добавлено в версии 3.3.

Изменено в версии 3.5: Добавлены атрибуты stdout и stderr

exception subprocess.CalledProcessError

Подкласс SubprocessError, возникающий, когда процесс, выполняемый check_call() или check_output(), возвращает ненулевой статус выхода.

returncode

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

cmd

Команда, которая использовалась для создания дочернего процесса.

output

Вывод дочернего процесса, если он был захвачен run() или check_output(). В противном случае None.

stdout

Псевдоним для вывода для симметрии с stderr.

stderr

Выходные данные stderr дочернего процесса, если они были захвачены run(). В противном случае None.

Изменено в версии 3.5: Добавлены атрибуты stdout и stderr

Часто используемые аргументы

Для поддержки широкого спектра вариантов использования конструктор Popen (и вспомогательные функции) принимает большое количество необязательных аргументов. В большинстве типичных случаев использования для многих из этих аргументов можно безопасно оставить значения по умолчанию. Наиболее часто используются следующие аргументы:

args требуется для всех вызовов и должен быть строкой или последовательностью аргументов программы. Как правило, предпочтительнее указывать последовательность аргументов, поскольку она позволяет модулю позаботиться о любом необходимом экранировании и закавычивании аргументов (например, разрешить пробелы в именах файлов). При передаче одной строки либо shell должно быть True (см. ниже), либо строка должна просто называть программу, которая будет выполняться, без указания каких-либо аргументов.

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

Если указаны encoding или errors, или text (также известный как universal_newlines) истинно, файловые объекты stdin, stdout и stderr будут открываться в текстовом режиме с использованием encoding и errors, указанных в вызове, или значений по умолчанию для io.TextIOWrapper.

Для stdin символы окончания строки '\n' во входных данных будут преобразованы в разделитель строк по умолчанию os.linesep. Для stdout и stderr все окончания строк в выводе будут преобразованы в '\n'. Дополнительные сведения см. в документации класса io.TextIOWrapper, когда аргумент newline его конструктора — None.

Если текстовый режим не используется, stdin, stdout и stderr будут открыты как двоичные потоки. Кодирование или преобразование конца строки не выполняется.

Добавлено в версии 3.6: Добавлены параметры encoding и errors.

Добавлено в версии 3.7: Добавлен параметр text в качестве псевдонима для universal_newlines.

Примечание

Атрибут новой строки файловых объектов Popen.stdin, Popen.stdout и Popen.stderr не обновляется методом Popen.communicate().

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

Изменено в версии 3.3: Когда universal_newlinesTrue, класс использует кодировку locale.getpreferredencoding(False) вместо locale.getpreferredencoding(). См. класс io.TextIOWrapper для получения дополнительной информации об этом изменении.

Примечание

Прочтите раздел Соображения безопасности перед использованием shell=True.

Параметры, наряду со всеми другими параметрами, более подробно описаны в документации конструктора Popen.

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

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

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=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None)

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

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

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

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

В POSIX, если args является строкой, строка интерпретируется как имя или путь выполняемой программы. Однако это можно сделать, только если не передать аргументы программе.

Примечание

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

>>> import shlex, subprocess
>>> command_line = input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print(args)
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Успешно!

Обратите внимание, в частности, что параметры (например, -input) и аргументы (например, eggs.txt), разделенные пробелом в оболочке, помещаются в отдельные элементы списка, в то время как аргументы, которые требуют экранирования кавычек или обратной косой черты при использовании в оболочке (например, имена файлов, содержащие пробелы или команда echo, показанная выше) являются отдельными элементами списка.

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

Изменено в версии 3.6: Параметр args принимает путеподобный объект, если shellFalse, и последовательность, содержащую путеподобные объекты в POSIX.

Изменено в версии 3.8: Параметр args принимает путеподобный объект, если shell равен False, и последовательность, содержащую байты и путеподобные объекты в Windows.

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

В POSIX с shell=True оболочка по умолчанию /bin/sh. Если args является строкой, строка определяет команду, выполняемую через оболочку. Означает, что у строки должно быть точно так же форматирование, как при вводе в приглашении оболочки. Включает, например, кавычки или обратную косую черту, экранирующие имена файлов с пробелами. Если args представляет собой последовательность, первый элемент определяет командную строку, а любые дополнительные элементы будут рассматриваться как дополнительные аргументы для самой оболочки. То есть Popen делает эквивалент:

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

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

Примечание

Прочтите раздел Соображения безопасности перед использованием shell=True.

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

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

Изменено в версии 3.3.1: bufsize теперь по умолчанию содержит значение -1, чтобы включить буферизацию по умолчанию в соответствии с поведением, ожидаемым большинством кода. В версиях, предшествующих Python 3.2.4 и 3.3.1, по умолчанию было неправильно установлено значение 0, которое не было буферизовано и допускало короткие чтения. Это было непреднамеренно и не соответствовало поведению Python 2, как ожидалось большинством кода.

Аргумент executable указывает программу замены, которую нужно выполнить. Очень редко нужно. Когда shell=False, executable заменяет программу для выполнения, указанную в args. Однако исходный args по-прежнему передается в программу. Большинство программ рассматривают программу, указанную в args, как имя команды, которое может отличаться от фактически выполняемой программы. В POSIX имя args становится отображаемым именем исполняемого файла в таких утилитах, как ps. Если shell=True, в POSIX аргумент executable указывает заменяющую оболочку для /bin/sh по умолчанию.

Изменено в версии 3.6: Параметр executable принимает путеподобный объект в POSIX.

Изменено в версии 3.8: Параметр executable принимает байты, а путеподобный объект в Windows.

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

Если preexec_fn установлен как вызываемый объект, данный объект будет вызываться в дочернем процессе непосредственно перед выполнением дочернего процесса. (Только POSIX)

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

Параметр preexec_fn небезопасно использовать при наличии потоков в вашем приложении. Дочерний процесс может зайти в тупик до вызова exec. Если вы должны его использовать, оставьте его тривиальным! Сведите к минимуму количество вызываемых вами библиотек.

Примечание

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

Изменено в версии 3.8: Параметр preexec_fn больше не поддерживается в субинтерпретаторах. Использование параметра в субинтерпретаторе вызывает RuntimeError. Новое ограничение может повлиять на приложения, развернутые в mod_wsgi, uWSGI и других встроенных средах.

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

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

Изменено в версии 3.2: Значение по умолчанию для close_fds было изменено с False на то, что описано выше.

Изменено в версии 3.7: В Windows значение по умолчанию для close_fds было изменено с False на True при перенаправлении стандартных дескрипторов. Теперь можно установить close_fds на True при перенаправлении стандартных дескрипторов.

pass_fds — необязательная последовательность файловых дескрипторов, которые должны оставаться открытыми между родительским и дочерним. Если указать любой pass_fds, то close_fds будет True. (Только POSIX)

Изменено в версии 3.2: Добавлен параметр pass_fds.

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

Изменено в версии 3.6: Параметр cwd принимает путеподобный объект в POSIX.

Изменено в версии 3.7: Параметр cwd принимает путеподобный объект в Windows.

Изменено в версии 3.8: Параметр cwd принимает байтовый объект в Windows.

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

Изменено в версии 3.2: Был добавлен restore_signals.

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

Изменено в версии 3.2: start_new_session был добавлен.

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

Примечание

Если указано, env должен предоставлять все переменные, необходимые для выполнения программы. В Windows для запуска параллельной сборки указанный env должен включать действительный SystemRoot.

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

Добавлено в версии 3.6: Добавлены encoding и errors.

Добавлено в версии 3.7: text был добавлен как более читаемый псевдоним для universal_newlines.

Если задано, startupinfo будет объектом STARTUPINFO, который передаётся в базовую функцию CreateProcess. creationflags, если задан, может быть одним или несколькими из следующих флагов:

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

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

Popen и другие функции в данном модуле, которые его используют, вызывают событие аудита subprocess.Popen с аргументами executable, args, cwd и env. Значение args может быть одной строкой или списком строк, в зависимости от платформы.

Изменено в версии 3.2: Добавлена поддержка менеджера контекста.

Изменено в версии 3.6: Деструктор Popen теперь выдает предупреждение ResourceWarning, если дочерний процесс всё ещё запущен.

Изменено в версии 3.8: Popen может использовать os.posix_spawn() в некоторых случаях для повышения производительности. В подсистеме Windows для Linux и пользовательской эмуляции QEMU конструктор Popen, использующий os.posix_spawn(), больше не вызывает исключение при таких ошибках, как отсутствие программы, но дочерний процесс завершается с ошибкой с ненулевым значением returncode.

Исключения

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

Чаще всего возникает исключение OSError. Это происходит, например, при попытке выполнить несуществующий файл. Приложения нужно подготовить к исключениям OSError.

ValueError будет вызван, если Popen вызывается с недопустимыми аргументами.

check_call() и check_output() вызовут CalledProcessError, если вызываемый процесс вернёт ненулевой код возврата.

Все принимающие параметр timeout функции и методы, например, call() и Popen.communicate(), будут вызывать TimeoutExpired, если время ожидания истечёт до завершения процесса.

Все исключения, определенные в данном модуле, наследуются от SubprocessError.

Добавлено в версии 3.3: Добавлен базовый класс SubprocessError.

Соображения безопасности

В отличие от некоторых других функций popen, реализация никогда не будет неявно вызывать системную оболочку. Это означает, что все символы, включая метасимволы оболочки, можно безопасно передавать дочерним процессам. Если оболочка вызывается явно через shell=True, ответственность за то, чтобы все пробелы и метасимволы были указаны правильно, во избежание уязвимостей инъекции оболочки, является обязанностью приложения.

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

Popen объекты

У экземпляров класса Popen есть следующие методы:

Popen.poll()

Проверить, не завершился ли дочерний процесс. Установить и вернуть атрибут returncode. В противном случае возвращает None.

Popen.wait(timeout=None)

Подождать, пока дочерний процесс завершится. Установить и вернуть атрибут returncode.

Если процесс не завершается через timeout секунд, вызвать исключение TimeoutExpired. Можно безопасно перехватить исключение и повторить ожидание.

Примечание

Приведёт к взаимоблокировке при использовании stdout=PIPE или stderr=PIPE, и дочерний процесс генерирует достаточно выходных данных для конвейера, чтобы он блокировал ожидание, пока буфер конвейера ОС не примет больше данных. Чтобы избежать этого, используйте Popen.communicate() при использовании конвейеров.

Примечание

Функция реализована с использованием цикла занятости (неблокирующий вызов и короткие засыпания). Используйте модуль asyncio для асинхронного ожидания: см. asyncio.create_subprocess_exec.

Изменено в версии 3.3: Был добавлен timeout.

Popen.communicate(input=None, timeout=None)

Взаимодействие с процессом: отправка данных на stdin. Считывать данные из stdout и stderr, пока не будет достигнут конец файла. Подождать, пока процесс завершится, и установить атрибут returncode. Необязательным аргументом input должны быть данные, которые нужно отправить дочернему процессу, или None, если данные не должны отправляться дочернему процессу. Если потоки открыты в текстовом режиме, input должен быть строкой. В противном случае — байтами.

communicate() возвращает кортеж (stdout_data, stderr_data). Данные будут строками, если потоки были открыты в текстовом режиме; в противном случае байты.

Обратите внимание: если вы хотите отправлять данные в stdin процесса, вам необходимо создать объект Popen с stdin=PIPE. Точно так же, чтобы получить что-либо, кроме None в результирующем кортеже, вам нужно также указать stdout=PIPE и/или stderr=PIPE.

Если процесс не завершится через timeout секунд, будет возбуждено исключение TimeoutExpired. Перехват этого исключения и повторная попытка связи не приведет к потере вывода.

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

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

Примечание

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

Изменено в версии 3.3: Был добавлен timeout.

Popen.send_signal(signal)

Посылает ребенку сигнал signal.

Примечание

В Windows SIGTERM — псевдоним для terminate(). CTRL_C_EVENT и CTRL_BREAK_EVENT могут быть отправлены процессам, запущенным с параметром creationflags, который включает CREATE_NEW_PROCESS_GROUP.

Popen.terminate()

Остановить ребёнка. В операционных системах POSIX метод отправляет SIGTERM дочернему элементу. В Windows для остановки дочернего вызывается функция Win32 API TerminateProcess().

Popen.kill()

Убивает дочерний процесс. В операционных системах POSIX функция отправляет дочернему элементу SIGKILL. В Windows kill() — псевдоним для terminate().

Также доступны следующие атрибуты:

Popen.args

Аргумент args, переданный в Popen — последовательность аргументов программы или отдельная строка.

Добавлено в версии 3.3.

Popen.stdin

Если аргумент stdin был PIPE, атрибут является записываемым объектом потока, возвращенным open(). Если были указаны аргументы encoding или errors или аргумент universal_newlines был True, поток является текстовым потоком, в противном случае это поток байтов. Если аргумент stdin не был PIPE, этот атрибут — None.

Popen.stdout

Если аргумент stdout был PIPE, атрибут является читаемым объектом потока, возвращенным open(). Чтение из потока обеспечивает вывод дочернего процесса. Если были указаны аргументы encoding или errors или аргумент universal_newlines был True, поток является текстовым потоком, в противном случае — потоком байтов. Если аргумент stdout не был PIPE, у этого атрибута значение None.

Popen.stderr

Если аргумент stderr был PIPE, атрибут является читаемым объектом потока, возвращенным open(). Чтение из потока обеспечивает вывод ошибок дочернего процесса. Если были указаны аргументы encoding или errors или аргумент universal_newlines был True, поток является текстовым потоком, в противном случае — потоком байтов. Если аргумент stderr не был PIPE, атрибут — None.

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

Используйте communicate(), а не .stdin.write, .stdout.read или .stderr.read, чтобы избежать взаимоблокировок из-за заполнения любого из других буферов конвейера ОС и блокировки дочернего процесса.

Popen.pid

ID дочернего процесса.

Обратите внимание, что если вы установить для аргумента shell значение True, будет ID процесса порождённой оболочки.

Popen.returncode

Дочерний код возврата, установленный poll() и wait() (и косвенно communicate()). Значение None указывает на то, что процесс ещё не завершён.

Отрицательное значение -N указывает, что дочерний был прерван сигналом N (только POSIX).

Помощники Windows Popen

Класс STARTUPINFO и следующие константы доступны только в Windows.

class subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)

Для создания Popen используется частичная поддержка структуры Windows STARTUPINFO. Следующие атрибуты можно установить, передав их только в виде ключевых аргументов.

Изменено в версии 3.7: Добавлена поддержка только ключевых аргументов.

dwFlags

Битовое поле, которое определяет, используются ли определенные атрибуты STARTUPINFO, когда процесс создает окно.

si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
hStdInput

Если dwFlags указывает STARTF_USESTDHANDLES, атрибут является стандартным дескриптором ввода для процесса. Если STARTF_USESTDHANDLES не указан, по умолчанию для стандартного ввода используется буфер клавиатуры.

hStdOutput

Если dwFlags указывает STARTF_USESTDHANDLES, атрибут является стандартным дескриптором вывода для процесса. В противном случае данный атрибут игнорируется, и по умолчанию для стандартного вывода используется буфер окна консоли.

hStdError

Если dwFlags указывает STARTF_USESTDHANDLES, атрибут является стандартным дескриптором ошибки для процесса. В противном случае данный атрибут игнорируется, и по умолчанию для стандартной ошибки используется буфер окна консоли.

wShowWindow

Если dwFlags указывает STARTF_USESHOWWINDOW, атрибут может быть любым из значений, которые могут быть указаны в параметре nCmdShow для функции ShowWindow, за исключением SW_SHOWDEFAULT. В противном случае данный атрибут игнорируется.

Для данного атрибута предоставляется SW_HIDE. Он используется, когда Popen вызывается с shell=True.

lpAttributeList

Словарь дополнительных атрибутов для создания процесса, как указано в STARTUPINFOEX, см. UpdateProcThreadAttribute.

Поддерживаемые атрибуты:

handle_list

Последовательность наследуемых дескрипторов. close_fds — истинно, если не пусто.

Дескрипторы временно необходимо сделать наследуемыми os.set_handle_inheritable() при передаче в конструктор Popen, иначе OSError вызовется с ошибкой Windows ERROR_INVALID_PARAMETER (87).

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

В многопоточном процессе соблюдайте осторожность, чтобы избежать утечки дескрипторов, помеченных как наследуемые, при объединении данной функции с одновременными вызовами других функций создания процесса, которые наследуют все дескрипторы, такие как os.system(). Это также относится к стандартному перенаправлению дескрипторов, которое временно создаёт наследуемые дескрипторы.

Добавлено в версии 3.7.

Константы Windows

Модуль subprocess предоставляет следующие константы.

subprocess.STD_INPUT_HANDLE

Стандартное устройство ввода. Изначально буфер ввода консоли, CONIN$.

subprocess.STD_OUTPUT_HANDLE

Стандартное устройство вывода. Изначально активный экранный буфер консоли, CONOUT$.

subprocess.STD_ERROR_HANDLE

Стандартное устройство ошибок. Изначально активный экранный буфер консоли, CONOUT$.

subprocess.SW_HIDE

Скрывает окно. Другое окно будет активировано.

subprocess.STARTF_USESTDHANDLES

Указывает, что атрибуты STARTUPINFO.hStdInput, STARTUPINFO.hStdOutput и STARTUPINFO.hStdError содержат дополнительную информацию.

subprocess.STARTF_USESHOWWINDOW

Указывает, что атрибут STARTUPINFO.wShowWindow содержит дополнительную информацию.

subprocess.CREATE_NEW_CONSOLE

У нового процесса новая консоль вместо наследования родительской консоли (по умолчанию).

subprocess.CREATE_NEW_PROCESS_GROUP

Параметр Popen creationflags, указывает, что будет создана новая группа процессов. Флаг необходим для использования os.kill() в подпроцессе.

Флаг игнорируется, если указан CREATE_NEW_CONSOLE.

subprocess.ABOVE_NORMAL_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет приоритет выше среднего.

Добавлено в версии 3.7.

subprocess.BELOW_NORMAL_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет приоритет ниже среднего.

Добавлено в версии 3.7.

subprocess.HIGH_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет высокий приоритет.

Добавлено в версии 3.7.

subprocess.IDLE_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет неактивный (самый низкий) приоритет.

Добавлено в версии 3.7.

subprocess.NORMAL_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет нормальный приоритет. (По умолчанию.)

Добавлено в версии 3.7.

subprocess.REALTIME_PRIORITY_CLASS

Параметр Popen creationflags, указывающий, что у нового процесса будет приоритет в реальном времени. Практически никогда не следует использовать REALTIME_PRIORITY_CLASS, потому что прерывает системные потоки, которые управляют вводом мыши, вводом с клавиатуры и фоновой очисткой диска. Данный класс может подходить для приложений, «общающиеся» напрямую с оборудованием или выполняют короткие задачи, у которых ограниченные перерывы.

Добавлено в версии 3.7.

subprocess.CREATE_NO_WINDOW

Параметр Popen creationflags, указывающий, что новый процесс не будет создавать окно.

Добавлено в версии 3.7.

subprocess.DETACHED_PROCESS

Параметр Popen creationflags, указывающий, что новый процесс не будет наследовать консоль своего родителя. Значение нельзя использовать с CREATE_NEW_CONSOLE.

Добавлено в версии 3.7.

subprocess.CREATE_DEFAULT_ERROR_MODE

Параметр Popen creationflags, указывающий, что новый процесс не наследует режим ошибки вызывающего процесса. Вместо этого новый процесс получает режим ошибки по умолчанию. Функция особенно полезна для многопоточных приложений оболочки, которые работают с отключенными серьезными ошибками.

Добавлено в версии 3.7.

subprocess.CREATE_BREAKAWAY_FROM_JOB

Параметр Popen creationflags, указывающий, что новый процесс не связан с заданием.

Добавлено в версии 3.7.

Старый высокоуровневый API

До Python 3.5 три функции составляли высокоуровневый API для подпроцессов. Теперь вы можете использовать run() во многих случаях, но множество существующих кодов вызывают данные функции.

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

Выполнить команду, описанную args. Дождаться завершения команды, затем вернуть атрибут returncode.

Код, которому требуется захват stdout или stderr, должен использовать вместо этого run():

run(...).returncode

Чтобы подавить stdout или stderr, укажите значение DEVNULL.

Приведенные выше аргументы — лишь некоторые общие. Полная сигнатура функции такая же, как у конструктора Popen — функция передаёт все предоставленные аргументы, кроме timeout, напрямую через данный интерфейс.

Примечание

Не используйте с функцией stdout=PIPE или stderr=PIPE. Дочерний процесс блокируется, если он генерирует достаточно выходных данных для конвейера, чтобы заполнить буфер конвейера ОС, поскольку конвейеры не читаются.

Изменено в версии 3.3: Добавлен timeout.

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

Запускает команду с аргументами. Дожидается завершения команды. Если код возврата был равен нулю, то возвращает его, в противном случае вызывает CalledProcessError. У объекта CalledProcessError будет код возврата в атрибуте returncode.

Код, которому требуется захват stdout или stderr, должен использовать вместо неё run():

run(..., check=True)

Чтобы подавить stdout или stderr, укажите значение DEVNULL.

Приведенные выше аргументы являются лишь частью общих. Полная сигнатура функции такая же, как у конструктора Popen — функция передаёт все предоставленные аргументы, кроме timeout, напрямую через данный интерфейс.

Примечание

Не использовать с данной функцией stdout=PIPE или stderr=PIPE. Дочерний процесс блокируется, если он генерирует достаточно выходных данных для конвейера, чтобы заполнить буфер конвейера ОС, поскольку конвейеры не читаются.

Изменено в версии 3.3: Был добавлен timeout.

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)

Запустить команду с аргументами и вернуть её вывод.

Если код возврата был ненулевым, возникает CalledProcessError. У объекта CalledProcessError будет код возврата в атрибуте returncode и любые выходные данные в атрибуте output.

Эквивалентно:

run(..., check=True, stdout=PIPE).stdout

Приведенные выше аргументы являются лишь частью общих. Полная сигнатура функции во многом такая же, как и у run() — большинство аргументов передаются напрямую в этот интерфейс. Существует одно отличие API от поведения run(): передача input=None будет вести себя так же, как input=b'' (или input='', в зависимости от других аргументов), вместо использования стандартного дескриптора входного файла родителя.

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

Данное поведение можно изменить, установив text, encoding, errors или universal_newlines на True, как описано в Часто используемые аргументы и run().

Чтобы также зафиксировать стандартную ошибку в результате, используйте stderr=subprocess.STDOUT:

>>> subprocess.check_output(
...     "ls non_existent_file; exit 0",
...     stderr=subprocess.STDOUT,
...     shell=True)
'ls: non_existent_file: No such file or directory\n'

Добавлено в версии 3.1.

Изменено в версии 3.3: Был добавлен timeout.

Изменено в версии 3.4: Добавлена поддержка ключевого аргумента input.

Изменено в версии 3.6: Добавлены encoding и errors. Подробнее см. run().

Добавлено в версии 3.7: text был добавлен как более читаемый псевдоним для universal_newlines.

Замена старых функций модулем subprocess

В этом разделе «a становится b» означает, что b можно использовать как замену a.

Примечание

Все функции «a» в этом разделе завершаются ошибкой (более или менее), если исполняемая программа не найдена; замена «b» вместо этого вызывает OSError.

Кроме того, замены с использованием check_output() завершатся ошибкой с CalledProcessError, если запрошенная операция выдаст ненулевой код возврата. Выходные данные по-прежнему доступны как атрибут output вызванного исключения.

В следующих примерах предполагается, что соответствующие функции уже импортированы из модуля subprocess.

Замена подстановки команд оболочки /bin/sh

output=$(mycmd myarg)

становится:

output = check_output(["mycmd", "myarg"])

Замена конвейера оболочки

output=$(dmesg | grep hda)

становится:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Разрешите p1 получить SIGPIPE, если p2 завершит работу.
output = p2.communicate()[0]

Вызов p1.stdout.close() после запуска p2 важен для того, чтобы p1 получил SIGPIPE, если p2 завершится до p1.

В качестве альтернативы для надежного ввода можно напрямую использовать поддержку собственного конвейера оболочки:

output=$(dmesg | grep hda)

становится:

output=check_output("dmesg | grep hda", shell=True)

Замена os.system()

sts = os.system("mycmd" + " myarg")
# становится
sts = call("mycmd" + " myarg", shell=True)

Заметки:

  • Вызов программы через оболочку обычно не требуется.

Более реалистичный пример мог бы выглядеть так:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print("Child was terminated by signal", -retcode, file=sys.stderr)
    else:
        print("Child returned", retcode, file=sys.stderr)
except OSError as e:
    print("Execution failed:", e, file=sys.stderr)

Замена семейства os.spawn

P_NOWAIT пример:

pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid

P_WAIT пример:

retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])

Векторный пример:

os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])

Пример окружения:

os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})

Замена os.popen(), os.popen2(), os.popen3()

(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
 child_stdout,
 child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
 child_stdout,
 child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

Обработка кода возврата переводится следующим образом:

pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
    print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
    print("There were some errors")

Замена функций из модуля popen2

Примечание

Если аргумент cmd для функций popen2 является строкой, команда выполняется через /bin/sh. Если список, команда выполняется напрямую.

(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen("somestring", shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)

popen2.Popen3 и popen2.Popen4 в основном работают как subprocess.Popen, за исключением следующего:

  • Popen вызывает исключение в случае сбоя выполнения.
  • Аргумент capturestderr заменяется аргументом stderr.
  • Необходимо указать stdin=PIPE и stdout=PIPE.
  • popen2 закрывает все файловые дескрипторы по умолчанию, но вы должны указать close_fds=True с Popen, чтобы гарантировать такое поведение на всех платформах или в предыдущих версиях Python.

Устаревшие функции вызова оболочки

Модуль также предоставляет следующие функции, унаследованные от модуля 2.x commands. Операции неявно вызывают системную оболочку, и ни одна из описанных выше гарантий безопасности и согласованности обработки исключений не действует для данных функций.

subprocess.getstatusoutput(cmd)

Вернуть (exitcode, output) при выполнении cmd в оболочке.

Выполнить строку cmd в оболочке с Popen.check_output() и вернуть двухкортежный (exitcode, output). Используется кодировка локали; см. примечания к Часто используемые аргументы для получения более подробной информации.

Завершающий символ новой строки удаляется из вывода. Код выхода для команды можно интерпретировать как код возврата подпроцесса. Пример:

>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
>>> subprocess.getstatusoutput('cat /bin/junk')
(1, 'cat: /bin/junk: No such file or directory')
>>> subprocess.getstatusoutput('/bin/junk')
(127, 'sh: /bin/junk: not found')
>>> subprocess.getstatusoutput('/bin/kill $$')
(-15, '')

Доступность: POSIX & Windows.

Изменено в версии 3.3.4: Добавлена поддержка Windows.

Теперь функция возвращает (код выхода, вывод) вместо (статус, вывод), как это было в Python 3.3.3 и ранее. У кода выхода то же значение, что и returncode.

subprocess.getoutput(cmd)

Возвращает вывод (stdout и stderr) выполнения cmd в оболочке.

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

>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'

Доступность: POSIX & Windows.

Изменено в версии 3.3.4: Добавлена поддержка Windows

Заметки

Преобразование последовательности аргументов в строку в Windows

В Windows последовательность args преобразуется в строку, которая может проанализирована с использованием следующих правил (соответствующие используемым средой выполнения MS C правилам):

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

См.также

shlex
Модуль предоставляет функцию для разбора и экранирования командных строк.