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

Методы объекта Popen модуля subprocess

При вызове subprocess.Popen() возвращает объект Popen, который имеет методы, описанные ниже.

Содержание:


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

Popen.poll():

Метод Popen.poll() проверяет, завершен ли дочерний процесс. Возвращает атрибут кода возврата Popen.returncode. В противном случае возвращает None.

>>> import time, subprocess
>>> proc = subprocess.Popen(['sleep', '30'])
>>> print(proc.poll())
# None

# после 30 секунд
>>> print(proc.poll())
# 0
>>> proc.returncode
# 0

Popen.wait(timeout=None):

Метод Popen.wait() ждет завершения дочернего процесса. Возвращает атрибут кода возврата Popen.returncode.

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

>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '10'])
>>> proc.wait()
# 0
>>> proc = subprocess.Popen(['sleep', '10'])
>>> proc.wait(5)
# Traceback (most recent call last):
#     raise TimeoutExpired(self.args, timeout)
# subprocess.TimeoutExpired: Command '['sleep', '10']' timed out after 5 seconds

Примечание:

  • Метод Popen.wait() приведет к взаимоблокировке при использовании stdout=subprocess.PIPE или stderr=subprocess.PIPE если дочерний процесс генерирует достаточно данных для канала. Метод блокирует ожидание буфера канала ОС для приема большего количества данных. Используйте метод Popen.communicate() при использовании каналов, чтобы избежать этого.
  • Метод реализован с использованием цикла занятости (неблокирующий вызов и короткие спящие режимы). Используйте модуль asyncio для асинхронного ожидания.

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

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

Если потоки были открыты в текстовом режиме (аргументы encoding или errors, или text=True, также известный как universal_newlines), то ввод должен быть строкой. В противном случае это должна быть, например байтовая строка.

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

>>> from subprocess import Popen, PIPE
>>> cmd = ['ls', '-Rla', '/tmp']
>>> proc = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding='utf-8')
>>> stdout, stderr = proc.communicate()
>>> print(stdout)
# /tmp:
# итого 76
# drwxrwxrwt 17 root   root   4096 мая 13 15:06 .
# drwxr-xr-x 26 root   root   4096 апр 30 09:18 ..
# drwxrwxrwt  2 root   root   4096 мая 13 07:35 .font-unix
# drwxrwxrwt  2 root   root   4096 мая 13 07:35 .ICE-unix
# ...
# ...
>>> print(stderr)
# ls: невозможно открыть каталог ... Отказано в доступе
# ls: невозможно открыть каталог ... Отказано в доступе
# ...
# ...

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

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

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

# псевдокод
proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

Примечание:

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

Popen.send_signal(signal):

Метод Popen.send_signal() посылает сигнал signal дочернему процессу.

>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '60'])
>>> proc.send_signal(9)
>>> proc.poll()
# -9

Примечание:

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

Popen.terminate():

Метод Popen.terminate() останавливает дочерний процесс.

  • В ОС Unix метод отправляет SIGTERM дочернему процессу.
  • В Windows вызывается Win32 API-функция TerminateProcess().
>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '60'])
>>> proc.terminate()
>>> proc.poll()
# -15

Popen.kill():

Метод Popen.kill() убивает дочерний процесс.

  • В ОС Unix функция отправляет SIGKILL ребенку.
  • В Windows метод Popen.kill() является псевдонимом Popen.terminate().
>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '60'])
>>> proc.kill()
>>> proc.poll()
-9

Атрибуты объекта Popen.

Popen.args:

Атрибут Popen.args() возвращает аргумент args в том виде, как он был передан в subprocess.Popen(). Представляет из себя список аргументов программы или отдельная строка.

Popen.stdin:

Если аргумент stdin=subprocess.PIPE, то атрибут Popen.stdin() является записываемым объектом потока, возвращаемым функцией open().

Если были заданы аргументы encoding или errors, или text=True (также известный как universal_newlines), то Popen.stdin() является текстовым потоком, в противном случае это поток байтов.

Если аргумент stdin не был равен subprocess.PIPE, то этот атрибут будет возвращать None.

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

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

Popen.stdout:

Если аргумент stdout=subprocess.PIPE, то атрибут Popen.stdout() является читаемым объектом потока, возвращаемым функцией open(). Чтение из потока stdout обеспечивает вывод генерируемых данных от дочернего процесса.

Если были заданы аргументы encoding или errors, или text=True (также известный как universal_newlines), то Popen.stdout() является текстовым потоком, в противном случае это поток байтов.

Если аргумент stdout не был равен subprocess.PIPE, то этот атрибут будет возвращать None.

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

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

Popen.stderr:

Если аргумент stderr=subprocess.PIPE, то атрибут Popen.stderr() является читаемым объектом потока, возвращаемым open (). Чтение из потока stderr обеспечивает вывод ошибок от дочернего процесса.

Если были заданы аргументы encoding или errors, или text=True (также известный как universal_newlines), то Popen.stderr() является текстовым потоком, в противном случае это поток байтов.

Если аргумент stderr не был равен subprocess.PIPE, то этот атрибут будет возвращать None.

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

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

Popen.pid:

Атрибут Popen.pid() возвращает идентификатор ID процесса дочернего процесса.

>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '10'])
>>> proc.pid
# 6016

Обратите внимание, что если аргумент shell=True, то это идентификатор процесса порожденный оболочкой.

Popen.returncode:

Атрибут Popen.returncode() это код возврата дочернего процесса, установленный Popen.poll() и Popen.wait() и косвенно - Popen.communicate(). Значение None указывает, что процесс еще не завершен.

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

>>> import subprocess
>>> proc = subprocess.Popen(['sleep', '20'])
>>> print(proc.returncode)
# None
>>> proc.terminate()
>>> proc.poll()
# -15
>>> proc.returncode
# -15