2016-12-22 3 views
2

Я пишу программу на python, которая вызывает другую программу с помощью команды subprocess.Popen.Дождитесь завершения процесса, созданного процессом

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

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

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

Я попытался это:

p = subprocess.Popen('/user/sbin/startprogramtolaunchgui') 
p.wait() 
printf 'done' 

Но «сделать» печатается сразу, а не после того, как графический интерфейс вышел из. Кроме того, когда я запускаю команду

ps -ef 

Программа «startprogramtolaunchgui», которую я вызывал, не входит в список процессов. НО, я вижу графический интерфейс, что он запущен в списке процессов (тот, который я хочу контролировать)

EDIT:

Я придумал это:

def isRunning(pid): 
     try: 
     os.kill(pid, 0) 
     return True 
     except OSError: 
     return False 


p = subprocess.Popen('/user/sbin/startprogramtolaunchgui') 
time.sleep(5) 
temp = subprocess.check_output(['pgrep', 'gui']) #get pid of GUI process 

while(isRunning(int(temp))): 
     pass 

print 'GUI CLOSED' 

Он работает. .. но это действительно хороший способ сделать это?

ответ

0

Это частичный/предварительный ответ. Изучите библиотеку psutil, в которой есть инструменты для определения дочерних процессов данного процесса и для ожидания завершения процессов. Вот эскиз подхода. Он имеет проблемы, но, надеюсь, это дает вам отправную точку для работы с:

import psutil 
parent = psutil.Process(p.pid) 
procs = set([parent]) 
while parent.is_running(): # hmm, OK, but what if one of the children spawns a grandchild *after* the parent has finished... 
    for child in parent.children(recursive=True): 
     procs.add(child) 
    # Hmm, here we are busy-waiting 

psutil.wait_procs(procs) 

Вот еще один подход, который может работать вокруг проблемы внучат-оф-мертвое-прародителей:

import psutil 
procs = {psutil.Process(p.pid)} 
while procs: 
    procs = {proc for proc in procs if proc.is_running()} 
    for proc in list(procs): 
     for child in proc.children(): 
      procs.add(child) 
    # Hmm, here we are busy-waiting 

Но вы может все еще иметь проблему «репарации», указанную в комментариях. Вышеупомянутые подходы могут работать, или вам может быть проще просто вызывать ps из Python и анализировать его вывод текста, ожидая появления какой-либо подписи вашего GUI-процесса, а затем исчезнет.

+0

Это может работать, но ненадежно. Когда родитель выйдет без прерывания доступа к дочерним элементам, дети получат reparented для pid 1 (init). Если вам посчастливилось запустить 'psutil' достаточно рано, когда ближайший ребенок еще не вышел, но уже породил дочерний процесс, вы могли бы обнаружить внуков.Вероятность этого может быть твердой или тонкой, в зависимости от поведения дочернего процесса. – 9000

1

Если вы используете p.wait(), вы также должны указать stdout=PIPE в качестве аргумента для вызова Popen.

Альтернативой является использование p.communicate(), который автоматически вызывает wait().

В любом случае это должно сработать.

+0

К сожалению, я не могу использовать p.wait(), потому что вызванный процесс сразу же прекращается. Я пытаюсь контролировать ДРУГОЙ процесс, вызванный процессом, который я вызываю – coder4lyf

+0

Если я правильно понял, A вызывает B, в котором отображается графический интерфейс. Вы говорите, что B заканчивается перед отображением GUI? Это не имеет смысла. –

+0

Нет, B отображает GUI (C), а затем B завершает – coder4lyf

Смежные вопросы