Python multiprocessing.Process在Linux下函数返回后进程未终止问题咨询
Linux下multiprocessing子进程目标函数返回后仍留存在进程表的问题
问题现象
在Linux系统中,使用multiprocessing模块启动的子进程,在目标函数执行完毕返回后,并不会立即从进程表中消失,而是会以僵尸进程的状态存在,直到父进程调用is_alive()方法,或者父进程退出才会被回收。而Windows系统下子进程会正常退出,符合预期。
示例程序
import multiprocessing import time def hello_word(): time.sleep(5) print("Hi mom, im in another process!") if __name__ == '__main__': multiprocessing.freeze_support() time.sleep(3) p = multiprocessing.Process(target=hello_word) p.start() time.sleep(15) print("Asking is_alive()") print(p.is_alive()) time.sleep(5)
程序输出
Hi mom, im in another process! Asking is_alive() False
异常监控结果
通过top、htop或ps grep等工具监控时会发现:
- 子进程在打印
Hi mom...后并未立即退出,而是等到父进程调用is_alive()时才被回收 - 若父进程从不调用
is_alive(),子进程会一直以僵尸状态存在,直到父进程退出
理解误区澄清
这并不是子进程没有终止,而是Linux系统特有的僵尸进程机制:
- 子进程执行完毕后,内核会保留该进程的退出状态等信息,直到父进程通过
wait()或waitpid()系统调用回收这些资源 multiprocessing.Process的is_alive()方法内部会触发wait()操作,因此调用后僵尸进程会被清理,外部工具就看不到了- Windows系统没有僵尸进程的概念,子进程终止后系统会直接回收资源,因此表现符合预期
不调用is_alive()的解决方法
以下几种方式可以让父进程主动回收子进程资源,避免僵尸进程:
1. 调用join()方法
join()方法会等待子进程终止(可设置超时),并自动回收子进程资源:
# 在p.start()之后调用join,若不需要阻塞可设置timeout p.start() # 非阻塞式检查并回收,timeout=0表示立即返回 p.join(timeout=0) # 或者阻塞等待子进程结束,适合不需要父进程并行执行其他任务的场景 # p.join()
2. 使用信号处理函数回收僵尸进程
注册SIGCHLD信号处理函数,在子进程终止时自动调用waitpid()回收资源:
import multiprocessing import time import signal import os def handle_sigchld(signum, frame): # 循环回收所有僵尸进程,os.WNOHANG表示非阻塞 while True: try: os.waitpid(-1, os.WNOHANG) except OSError: # 没有更多僵尸进程时退出循环 break def hello_word(): time.sleep(5) print("Hi mom, im in another process!") if __name__ == '__main__': multiprocessing.freeze_support() # 注册信号处理函数 signal.signal(signal.SIGCHLD, handle_sigchld) time.sleep(3) p = multiprocessing.Process(target=hello_word) p.start() time.sleep(20)
3. 使用multiprocessing.Pool管理进程
如果需要启动多个子进程,Pool会自动处理进程的创建和回收,无需手动操作:
import multiprocessing import time def hello_word(): time.sleep(5) print("Hi mom, im in another process!") if __name__ == '__main__': multiprocessing.freeze_support() time.sleep(3) # 创建进程池,这里设置1个进程示例 with multiprocessing.Pool(1) as pool: pool.apply_async(hello_word) # 等待所有任务完成 pool.close() pool.join() time.sleep(10)
内容的提问来源于stack exchange,提问作者SurGe
相关产品推荐
相关产品推荐

