При вызове subprocess.Popen()
возвращает объект Popen
, который имеет методы, описанные ниже.
Popen.poll()
, Popen.wait()
, Popen.communicate()
,Popen.send_signal()
,Popen.terminate()
,Popen.kill()
,Popen.args()
,Popen.stdin()
,Popen.stdout()
,Popen.stderr()
,pid
процесса Popen.pid()
,Popen.returncode()
.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
Примечание:
SIGTERM
является псевдонимом Popen.terminate()
. CTRL_C_EVENT
и CTRL_BREAK_EVENT
можно отправлять процессам, запущенным с параметром creationflags
, который включает CREATE_NEW_PROCESS_GROUP
.Popen.terminate()
:Метод Popen.terminate()
останавливает дочерний процесс.
SIGTERM
дочернему процессу. TerminateProcess()
.>>> import subprocess >>> proc = subprocess.Popen(['sleep', '60']) >>> proc.terminate() >>> proc.poll() # -15
Popen.kill()
:Метод Popen.kill()
убивает дочерний процесс.
SIGKILL
ребенку. 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