我有一个后台进程与主进程一起运行,它使用Queue
进行通信(使用多处理,而不是多线程(。主进程不断运行,后台线程每个队列项运行一次,因此即使它被积压,它仍然可以赶上。与其使用主脚本关闭(我已经为此启用了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
我遇到了is_alive()
,并认为也许从current_process()
获取主进程可能会起作用,但是当我尝试将其发送到队列时,它给出了一个选择错误。
Queue.get
有一个关键字参数timeout
,该参数确定队列为空时等待项目的时间。如果在超时过后没有可用项,则会引发Empty
异常。
从队列中删除并返回项目。如果可选的 args 块为 true,超时为 None (默认值(,则在必要时阻止,直到项目可用。如果超时为正数,则最多阻止超时秒数,并在该时间内没有可用项时引发 Empty 异常。否则(块为 false(,如果立即可用,则返回一个项目,否则引发 Empty 异常(在这种情况下忽略超时(。
因此,您可以排除该错误并脱离循环:
try:
received_data = q_recv.get(timeout=300)
except queue.Empty:
return