跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Python 如何一次性终止某个子进程下面的所有子进程?
未分類
1 1 月 2021

Python 如何一次性终止某个子进程下面的所有子进程?

Python 如何一次性终止某个子进程下面的所有子进程?

資深大佬 : zictos 0

比如主进程 m 创建了子进程 p
子进程 p 又创建了子进程 p1 、p2 、p3 、p4,甚至 p1 下面又有创建别的子进程。

在主进程 m 处用 p.kill()或者 p.terminate()可以终止子进程 p,但是 p 创建的子进程 p1,p2,p3,p4 还会继续保持运行。

希望一次性把子进程 p 以及子进程 p 下面的子进程全部结束,并且主进程 m 继续保持运行。有办法吗?

ps:■■■■■■■■■■■■■■■■■■
官方帮助中有说到关于 terminate()的注意事项:进程的后代进程将不会被终止 —— 它们将简单地变成孤立的。

这样的话感觉 kill()或 terminate()有点坑,比如你的某个子进程使用到了某个第三方模块,该模块里面也用到了多进程,而你如果直接 kill 掉该子进程,但子进程下面创建的子进程却并不能 kill 掉,而且可能不容易察觉到,毕竟第三方模块不是自己写的。

大佬有話說 (26)

  • 資深大佬 : black11black

    提一个思路,开一个子线程运行 terminal,通过 ps 命令获取完整进程树,Linux 中应该不算繁重操作,效率可以。

  • 資深大佬 : emSaVya

    进程组

  • 資深大佬 : codehz

    得区分系统,windows 10 下大概可以使用 job 对象配合 silo 隔离
    linux 可以用 pid namespace 隔离

  • 主 資深大佬 : zictos

    @black11black #1
    @emSaVya #2
    能识别是哪个子进程下面的子进程吗?因为可能有多个进程,并且不同进程下面都有子进程,而我只需要结束某个子进程以及该子进程下面的子进程。

    python 我只知道能直接获取当前进程下面的所有子进程的 pid (子进程下面的子进程好像不行),对于我题的例子来说,能不能直接在主进程 m 处获取子进程 p 下面的所有子进程的 pid 列表呢?然后再分别终止对应 pid 。
    或者如果事先对每个子进程进行有规则的命名,有没有办法通过名称来达到直接终止进程的目的呢?

  • 主 資深大佬 : zictos

    笨办法不是没有,比如每创建一个子进程就把子进程的 pid 以及归属哪个父进程的信息写入全局变量中或写入数据库或者写入文本中,然后结束时一个个判断 pid 属于哪个分组并且判断是否存在就行了。只是不知道有没有更简单的,可能有,但是没发现。另外如果是第三方模块创建的子进程这么做就不行了

  • 資深大佬 : tonic

    https://github.com/douban/CaoE

    嘻嘻嘻, 教授封装过

  • 資深大佬 : fish267

    1. 子线程,带个是否退出标志,自己轮询
    2. thread.join()

  • 資深大佬 : Jirajine

    psutil

  • 資深大佬 : tonic

    似乎跟你场景有点差别, 不过可以参考下自己封装个 =.=

  • 資深大佬 : codehz

    跟踪进程的方法有竞争条件,而且还有可能故意逃逸(比如 fork 两次 setsid 就出去了(
    思考下 android 的停止运行功能是怎么被绕过的(

  • 資深大佬 : lsc

    试试执行 shell,kill -9 pstree ?

  • 資深大佬 : black11black

    @zictos 参考命令`ps ax -o pid,ppid,cmd`,可以直接构建出树,唯一瑕疵是这是请求全系统的树,浪费了资源。

  • 資深大佬 : yucongo

    import psutil

    parent_pid = 30437
    parent = psutil.Process(parent_pid)
    for child in parent.children(recursive=True): # or parent.children() for recursive=False
    …. child.kill()
    parent.kill()

    SO 答案

  • 主 資深大佬 : zictos

    @tonic #6
    其实把子进程设为守护进程就可以让子进程在父进程被杀死时自动退出,但守护进程下面不能再创建子进程了。
    p = Process(target=test) #创建子进程 p
    p.daemon = True #把子进程 p 设为守护进程
    p.start()

  • 主 資深大佬 : zictos

    @yucongo #13
    可用,不过你的代码好像根本描述的效果不一样,我刚自己写着尝试了一下。把下面代码中的“[四空格]”替换成真正的 4 个空格就可以直接运行了
    ■■■■■■■■分割■■■■■■■■■■

    from multiprocessing import Process
    import psutil, os, time

    def test1():
    [四空格]print(‘我是主线程创建的第一个子线程,我的 pid 是%s’ % os.getpid())
    [四空格]#在第一个子线程下面继续创建子线程
    [四空格]p2 = Process(target=test2)
    [四空格]p2.start()
    [四空格]time.sleep(1000)

    def test2():
    [四空格]print(‘我是子线程创建的子线程,是主线程的孙线程,我的 pid 是%s’ % os.getpid())
    [四空格]#在第二个子线程下面继续创建子线程
    [四空格]p3 = Process(target=test3)
    [四空格]p3.start()
    [四空格]time.sleep(1000)

    def test3():
    [四空格]print(‘我是主线程的孙线程创建的子线程,我的 pid 是%s’ % os.getpid())
    [四空格]time.sleep(1000)

    if __name__ == ‘__main__’:
    [四空格]#创建子线程 p1
    [四空格]p1 = Process(target=test1)
    [四空格]p1.start()

    [四空格]#获取子线程 p1 的 pid
    [四空格]pid = p1.pid

    [四空格]#等待 4 秒后获取子线程 p1 下面所有子线程的 pid
    [四空格]time.sleep(4)
    [四空格]pidlist = psutil.Process(pid).children(recursive=True)
    [四空格]print(‘pid 为%s 下面的所有子线程为%s’ % (pid, pidlist))

  • 主 資深大佬 : zictos

    15 写错了,“进程”二字全部写成了“线程”

  • 資深大佬 : abersheeran

    这个事可以是各个进程主动检测自己的父进程是否存活,也可以是各个拥有子进程的父进程在退出前杀死自己所有的子进程。

  • 資深大佬 : JCZ2MkKb5S8ZX9pq

    有类似需求,现在用的就是记 pid 的笨办法,蹲一个。

  • 資深大佬 : fuse

    cgroup
    鼎鼎大名 systemd 实现方式不知道

  • 主 資深大佬 : zictos

    @abersheeran #17
    @JCZ2MkKb5S8ZX9pq #18

    15 已经解决了,已经可以获取到子进程对象了,杀进程可以再加一个循环
    for i in pidlist:
    ####i.kill()

  • 主 資深大佬 : zictos

    写成函数,只要传入某个进程的 pid 就可以杀死该进程以及该进程下面的子进程。把 killprocess(pid)中的 pid 替换为要杀的进程的 pid 即可

    def killprocess(pid):
    ****import psutil
    ****childlist = psutil.Process(pid).children(recursive=True)
    ****for i in childlist:
    ********i.kill()
    ****psutil.Process(pid).kill()

  • 資深大佬 : abersheeran

    @zictos 学到了。 原来还可以这么获取全部下属进程。

  • 資深大佬 : julyclyde

    @zictos 你这个似乎只能 kill 一层?
    正确的做法应该是深度优先遍历然后再从最深层往上 kill 吧

  • 主 資深大佬 : zictos

    @julyclyde #23
    针对 21 的代码,childlist 就已经包含了所有子进程对象了,直接用 for 遍历再逐个 kill 自然就是把所有子进程都杀死了。
    最后一行 psutil.Process(pid).kill()是杀死 pid 为传入的 pid 的进程,前面的 for 是杀死 pid 下面的子进程、孙进程……

  • 資深大佬 : julyclyde

    @zictos 哦。看到 recursive 了。不过顺序正确吗?

  • 主 資深大佬 : zictos

    @julyclyde #25 我没研究过顺序,你可以自己测试下。反正我问题中的需求就是希望能获取某个进程下所有的子进程以及孙进程等等等等,然后杀死他们。所以顺序根本就不重要。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具