You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程Queue关闭后子进程未终止及状态查询问题

多进程与multiprocessing.Queue问题解答

原问题代码

import random
import time
import multiprocessing

def fun(queue_value):
    sleep_value = random.choice(range(1, 20))
    time.sleep(sleep_value)
    queue_value.put(sleep_value, 3)

value = None
queue_value = multiprocessing.Queue()
process = multiprocessing.Process(target=fun, args=(queue_value,))  # 原代码此处缺少逗号,属于语法错误
process.daemon = True

process.start()
print('PID', process.pid) #pid shows as 93848

time.sleep(10) # sleeps for 10 sec and then check for the value and the queue will be closed

if not queue_value.empty():
    print(queue_value.get(timeout=3))

queue_value.close()
queue_value.join_thread() # As per the python doc, join_thread() should used only after calling close()
process.join()

if process.is_alive():
    print('process is still alive')
    process.terminate()

print('Is process alive', process.is_alive(), process.exitcode)

问题描述

当fun函数中的sleep_value取值大于10(比如18)时,主进程休眠10秒后关闭并join队列,此时无法获取队列中的值,子进程仍会继续休眠8秒。按照Python文档要求,应在join进程前关闭或join队列,但调用process.join()后子进程仍存活,执行process.terminate()后输出仍显示子进程存活(Is process alive True None)。

问题1:为何子进程未终止?是否因为子进程在queue_value.close()后尝试向队列put值?

另外,主程序结束前用ps -ef未查到该子进程PID,说明子进程已终止。

问题2:如何判断该子进程是否成功退出?

额外问题:采用无Pool的同步多进程方式终止子进程是否可行?有时会产生僵尸进程,该如何处理?


问题解答

问题1解答

先纠正原代码的几个关键错误:

  1. random.choise拼写错误,应为random.choice
  2. args=(queue_value)缺少逗号,需写成args=(queue_value,),否则会将Queue对象直接作为参数传递,导致函数参数不匹配
  3. time.sleep()缺少参数,应为time.sleep(sleep_value)

回到核心问题:

  • 子进程在queue_value.close()后尝试put值时,会触发BrokenPipeError,若未捕获异常,子进程会因未处理的异常直接崩溃退出。
  • 你看到process.is_alive()返回True且exitcode为None,是因为进程状态同步存在延迟:主进程调用terminate()后,操作系统需要时间完成子进程终止操作,而Python的进程对象状态不会立即同步系统状态。但ps -ef查不到PID,说明子进程已经被系统实际终止。

问题2解答

判断子进程是否成功退出,需结合以下几点:

  • 优先检查process.exitcode:只要值不为None,就说明进程已经终止。不同值的含义:
    • exitcode == 0:进程正常退出
    • exitcode > 0:进程因未处理的异常崩溃退出
    • exitcode < 0:进程被系统信号终止(比如SIGTERM对应-15,SIGKILL对应-9)
  • 不要仅依赖is_alive(),可在调用terminate()后短暂休眠(如time.sleep(0.1)),再调用is_alive()或检查exitcode,结果会更准确。
  • 直接通过系统工具验证:比如ps -ef | grep <PID>(Linux)或tasklist(Windows),这是最准确的方式。

额外问题解答

  1. 无Pool的同步多进程终止子进程完全可行:直接调用process.terminate()即可向子进程发送终止信号,绝大多数场景下都能正常终止子进程。
  2. 僵尸进程的处理方案:
    • 僵尸进程是子进程终止后,父进程未调用wait()或join()回收其资源导致的。在Pythonmultiprocessing中,调用process.join()会自动完成资源回收,避免僵尸进程。
    • 若设置process.daemon = True,主进程退出时,所有守护进程会被自动终止并回收资源,不会遗留僵尸进程。
    • 避免子进程终止后长时间不调用join(),确保父进程及时回收子进程资源。

内容的提问来源于stack exchange,提问作者Vishak Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:30:27