Как получить код выхода из subprocess.Popen?
В приведенном ниже коде p.returncode
всегда None
. Согласно Popen.returncode
документации, это означает, что процесс еще не завершен.
Почему я не получаю код выхода?
import os
import sys
import subprocess
cmd = ['echo','hello']
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
# Filter stdout
for line in iter(p.stdout.readline, ''):
sys.stdout.flush()
# Print status
print(">>> " + line.rstrip())
sys.stdout.flush()
except:
sys.stdout.flush()
print 'RETURN CODE', p.returncode
Обратите внимание: причина, по которой я читаю каждую строку отдельно, заключается в том, что я хочу фильтровать выходные данные других длительных процессов в режиме реального времени и останавливать их на основе определенных строк.
Я на Python 2.7.5 (CentOS 7 64-бит).
Решение
Благодаря ответу, отправленному @skyking, теперь я могу успешно захватить код выхода следующим образом: Popen.poll()
(Popen.wait()
заблокировал мой процесс):
import os
import sys
import subprocess
import time
cmd = ['echo','hello']
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
# Filter stdout
for line in iter(p.stdout.readline, ''):
sys.stdout.flush()
# Print status
print(">>> " + line.rstrip())
sys.stdout.flush()
except:
sys.stdout.flush()
# Wait until process terminates (without using p.wait())
while p.poll() is None:
# Process hasn't exited yet, let wait some
time.sleep(0.5)
# Get return code from process
return_code = p.returncode
print 'RETURN CODE', return_code
# Exit with return code from process
sys.exit(return_code)
Ответы
Ответ 1
В соответствии с документацией
Код возврата ребенка, установленный poll() и wait() (и косвенно общаться()). Значение None указывает, что процесс еще не завершился.
Отрицательное значение -N указывает, что ребенок был прерван сигналом N (только для Unix).
Вы не вызывали poll
или wait
, поэтому returncode
не будет установлен.
С другой стороны, если вы посмотрите на исходный код для fx check_output
, вы увидите, что они напрямую используют возвращаемое значение из poll
для проверки кода возврата. Они знают, что процесс завершился в этот момент, потому что они раньше называли wait
. Если вы не знаете, что вам придется называть метод wait
вместо этого (но обратите внимание на ту тупиковую возможность, отмеченную в документации).
Обычно программа прекращается, когда вы читаете все stdout/stderr, но это не гарантируется, и это может быть то, что вы видите. Либо программа, либо ОС могут закрыть stdout
(и stderr
) до того, как процесс действительно завершится, а затем просто позвонив poll
сразу после того, как вы прочитали все выходные данные программы, могут выйти из строя.