Python 检测主进程是否已从后台进程退出

Python 检测主进程是否已从后台进程退出,python,multiprocessing,Python,Multiprocessing,我有一个单独的后台进程与主进程并行运行,它使用队列进行通信(使用多处理,而不是多线程)。主进程持续运行,后台线程对每个队列项运行一次,这样,如果它被积压,它仍然可以赶上。与其用主脚本关闭(我已经为此启用了守护进程),我更希望它一直运行到队列为空,然后保存并退出 事情是这样开始的: q_send = Queue() q_recv = Queue() p1 = Process(target=background_process, args=(q_send, q_recv)) p1.daemon =

我有一个单独的后台进程与主进程并行运行,它使用
队列
进行通信(使用多处理,而不是多线程)。主进程持续运行,后台线程对每个队列项运行一次,这样,如果它被积压,它仍然可以赶上。与其用主脚本关闭(我已经为此启用了
守护进程
),我更希望它一直运行到队列为空,然后保存并退出

事情是这样开始的:

q_send = Queue()
q_recv = Queue()
p1 = Process(target=background_process, args=(q_send, q_recv))
p1.daemon = True
p1.start()
以下是后台进程当前的运行方式:

while True:

    received_data = q_recv.get()
    #do stuff
我考虑过的一种方法是将循环切换为始终运行,但在尝试读取之前检查队列的大小,如果队列为空,请等待几秒钟,然后重试。不过有几个问题。关键是它将每个项目运行一次,因此如果有1000个排队的命令,那么在每个命令之前检查队列大小似乎有点效率低下。此外,主进程在不发送更新的情况下可以运行多长时间没有真正的限制,因此我必须将超时设置得相当高,而不是在连接中断、队列清空时立即退出。由于后台线程使用高达2gb的ram,可能需要尽快退出

这也会让它看起来更混乱:

afk_time = 0
while True:

    if afk_time > 300:
        return
    if not q_recv.qsize():
        time.sleep(2)
        afk_time += 2
    else:
        received_data = q_recv.get()
        #do stuff
我偶然发现,并认为从中获取主进程可能会起作用,但当我尝试将其发送到队列时,它给出了一个拾取错误。

有一个关键字参数
timeout
,用于确定队列为空时等待项目的时间。如果超时时间过后没有可用项,则引发异常

从队列中删除并返回项目。如果optional args block为true,timeout为None(默认值),则根据需要进行阻塞,直到某个项可用。如果timeout为正数,则它最多会阻止超时秒,如果在此时间内没有可用项,则引发空异常。否则(block为false),如果立即可用,则返回一个项目,否则引发空异常(在这种情况下忽略超时)

因此,您可以排除该错误并中断循环:

try:
    received_data = q_recv.get(timeout=300)
except queue.Empty:
    return

谢谢,如果没有更好的解决方案,我可能会这样做,仍然无法解决我提到的第二个问题,但现在可以,我必须测试发送内容的频率,以尽可能降低超时时间:)@Peter你能再次指出你的确切目标吗?我觉得我错过了什么(特别是第二个问题)。为什么要退出后台进程?如果主进程稍后向队列发送了一些内容,该怎么办?我只希望它在主进程退出后结束,因为这意味着不再添加任何队列项目。我需要它做的就是完成队列的处理,因此超时可以作为一种解决方法,但最好的情况是它可以立即知道主进程已结束,而不需要任何超时。@Peter在这种情况下,您可以在队列上发送关闭命令。按照惯例,某些东西表明主要进程完成了它的工作。当后台收到此项时,它也可以终止。您只需要给出关闭命令的定义(例如
None
)。如果我能捕捉到主进程关闭,我可以这样做,但我的意思是退出,因为用户关闭了窗口。我研究了在脚本退出时执行python代码,但没有任何运气。