生成一个后台进程并阻塞等待它完成

Posted

技术标签:

【中文标题】生成一个后台进程并阻塞等待它完成【英文标题】:Spawn a background process and have a blocking wait on it to finish 【发布时间】:2021-07-26 09:49:07 【问题描述】:

我的场景是这样的:我需要在后台从另一个 python 脚本(进程 1)运行一个 python 脚本(进程 2)。然后我想在脚本 1 中对进程 2 进行阻塞等待,因为我想使用脚本 2 输出的文件。例如,考虑这个最小的例子:

脚本 1

import subprocess
import time

def get_pid_from_line(line):
    temp = [x for x in line.split() if len(x) != 0]
    return int(temp[1])

def blocking_wait(pid):
    while True:
        ps_output = subprocess.check_output("ps -ef | grep -E 'python.*<defunct>'", shell=True).decode("utf-8")
        ps_list = [line.strip() for line in ps_output.split("\n") if len(line.strip()) != 0]
        ps_list = [get_pid_from_line(line) for line in ps_list]
    
        if(pid in ps_list):
            break
        
        time.sleep(5)

p = subprocess.Popen(["python", "test2.py", "&"], shell=False)  # shell false required to get the correct pid, no longer can use string command :P
print(p.pid, type(p.pid))
# subprocess.call(f"wait p.pid", shell=True) # this again doesn't work
blocking_wait(p.pid)
print("world")

脚本 2

import time
import sys

for i in range(10):
    print("hello")
    time.sleep(2)

此代码有效,但我面临的问题是脚本 2 完成后,进程 2(在脚本 1 中使用 pid p.pid)成为僵尸,因此我在僵尸 python 进程列表中搜索 pid。为什么会发生这种情况?此外,搜索 pid 是否是僵尸 python 进程的逻辑似乎很脆弱。我尝试使用wait pid,但问题是它是非阻塞的,这会破坏我的逻辑,因为尚未创建文件。一般来说,这个解决方案有效但并不优雅,有没有更好的方法来做到这一点? TIA。

【问题讨论】:

【参考方案1】:

我不确定它是否适合您的应用程序,但我通常使用多处理模块中的events

这个概念是一个非常简单的信号行为,因为所有线程/进程都可以访问这个信号。在你的情况下,它会像:

    清除进程 1 中的事件 - event.clear() 启动进程 2 等待进程 1 中的事件 - event.wait() 完成后在进程 2 中设置事件 - event.set()

一旦调用event.set(),所有等待此事件的进程/线程都会立即恢复工作。

【讨论】:

以上是关于生成一个后台进程并阻塞等待它完成的主要内容,如果未能解决你的问题,请参考以下文章

获取前一段时间完成的后台进程的退出代码

运行并从后台进程获取输出

linux之创建守护进程

非阻塞等待子进程退出

等待来自父母的信号并再次完成工作和阻塞

c++后台开发面试常见知识点总结操作系统