python kill 主线程后如何让子线程也停止执行?

ztj1993
  • 56

这是我写的测试用例代码,可以执行后, kill -9 主线程后,子线程并没有退出,仍然在执行,但是如果 ctrl+c,却可以停掉所有的线程。请问如何在父进程结束时,自动回收子进程,谢谢!

如果有 pip 模块能解决此问题就更好了。

这是我的测试用例代码:

# -*- coding: utf-8 -*-
# Author: Ztj

import time
from multiprocessing import Process


class Listen(object):

    def listen(self, ):
        """监听"""
        for i in range(3):
            p = Process(name='Job', target=self.listen_callback, args=(i,))
            p.start()

    @staticmethod
    def listen_callback(i):
        """定时进程回调"""
        while True:
            print('正在执行中(%s)......' % i)
            time.sleep(1)


if __name__ == '__main__':
    listen = Listen()
    listen.listen()
回复
阅读 5.7k
2 个回答
✓ 已被采纳

之前也解决过这样的问题,用到了psutil模块,原理就是子进程定期检查父进程是否存在,不存在就退出。例子如下:

from multiprocessing import Process
import time
import psutil
import os

def worker(pid, n):
    pps = psutil.Process(pid=pid)
    while True:
        try: 
            if pps.status() in (psutil.STATUS_DEAD, psutil.STATUS_STOPPED):
                break
        except psutil.NoSuchProcess:
            break

        # 处理...
        print(n, time.time())
        time.sleep(1)


if __name__ == '__main__':
    ps = []
    pid = os.getpid()
    for code in ('aa','bb','cc'):
        p = Process(target=worker, args=(pid, code,))
        p.daemon = True
        p.start()
        ps.append(p)
    
    for p in ps:
        p.join()
    
    print('parent exit!!!!!!')
  1. 首先纠正概念,你用的是多进程,而不是线程
  2. 你的代码中主进程并没有做同步和控制的工作。主进程里应该注册信号处理函数,捕获特定信号,对子进程terminate()
  3. 但是使用 kill -9 野蛮杀死主进程,主进程根本没机会运行信号处理函数,子进程都变成孤儿进程。

@weizw 提供的方法是子进程自查自杀。可以避免孤儿进程继续存活。不过还请首先做到2.说的,主进程要能响应非SIGKILL信号,承担终止子进程的责任。

  1. Ctrl + C 能终止所有进程是因为 SIGINT 能触发所有前台进程的KeyboardInterrupt异常。

一个思考题:
你的代码跑起来后,kill掉主进程,这时原先的三个子进程还在跑,并且打印屏幕,这时Ctrl+C是否还能终止它们?为什么?
看懂了APUE的信号和进程控制部分,心里就会有答案了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏