【问题标题】:Wait for a process to end that is created by a process called等待由名为的进程创建的进程结束
【发布时间】:2017-05-08 14:33:10
【问题描述】:

我正在用 python 编写一个程序,它通过subprocess.Popen 命令调用另一个程序。

被调用的程序会启动一个与用户交互的 GUI,但在此之前它会通过一些服务对用户进行身份验证。

话虽如此,我正试图找出一种方法来了解用户何时退出该 GUI。基本上,我想等到 GUI 退出,然后在我的程序中继续。

我的问题是,由于我调用的程序在实际启动 GUI 之前通过了这些服务,所以我调用的程序似乎结束了,然后产生了一个新进程,即 GUI,然后'无法等待 pid,因为我的 pid 已经终止。

我试过这个:

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

但“完成”会立即打印,而不是在退出 GUI 之后。另外,当我运行命令时

ps -ef

我调用的程序“startprogramtolaunchgui”不在进程列表中。但是,我看到它在进程列表中启动的 gui(我要监视的那个)

编辑:

我想出了这个:

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'

它有效......但这真的是一个好的方法吗??

【问题讨论】:

    标签: python subprocess wait popen waitpid


    【解决方案1】:

    这是一个部分/暂定的答案。调查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
    

    但是您可能仍然有 cmets 中指出的“重养”问题。上述方法可能有效,或者您最好从 Python 中重复调用 ps 并解析其文本输出,等待您的 GUI 进程在那里出现然后消失的任何签名。

    【讨论】:

    • 这可能有效但不可靠。当父级在没有终止子级的情况下退出时,子级将重新设置为 pid 1(init)。如果您碰巧足够早地运行psutil,当直接子进程尚未退出但已经产生子进程时,您可能能够检测到孙子进程。根据子进程的行为,这种情况的可能性可能很大或很小。
    【解决方案2】:

    如果您使用p.wait(),您还应该包含stdout=PIPE 作为Popen 调用的参数。

    另一种方法是使用p.communicate(),它会自动为您调用wait()

    任何一种方式都应该有效。

    【讨论】:

    • 不幸的是我不能使用 p.wait() 因为被调用的进程被立即终止。我正在尝试监视由我调用的进程调用的另一个进程
    • 如果我理解正确,A 调用 B,它显示一个 GUI。您是说 B 在显示 GUI 之前终止吗?这没有意义。
    • 不,B 显示 GUI (C) 然后 B 终止
    • A 调用 B,B 调用 C,C 显示 GUI,B 终止。我对么?然后你应该在进程 B 中等待,直到使用 GUI。
    • 我想在进程 A 中等待,直到 GUI 使用完毕
    猜你喜欢
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2015-10-25
    相关资源
    最近更新 更多