首页 > 解决方案 > 如何获取孩子并退出 python 多处理池

问题描述

我正在尝试做的事情:

如果在创建多处理池后发生异常,则子进程在父进程终止时成为僵尸进程。为了解决这个问题,我捕获了异常,并明确地收获了池中的所有孩子。

问题是

这会导致父进程挂起,而不是退出并返回到终端命令行。

后一种行为是出乎意料的,我不明白为什么。但是回溯表明这是池中的问题。

问题是 为什么会挂起?

import multiprocessing as mp
 
def deadPool():
    print("Everybody out of the pool")
    active = mp.active_children()
    for a in active:
        print("reaping",a)
        a.terminate()
    print('deadpool')
   
try:
    pool = mp.Pool(mp.cpu_count()//2)
    print (" running with pool of ",mp.cpu_count()//2)
    p = 1/0  # intentional bug to generate exception
    
finally:
    deadPool()

这是对此的调用:

python ~/Documents/testMp.py 
 running with pool of  4
Everybody out of the pool
reaping <ForkProcess(ForkPoolWorker-1, started daemon)>
reaping <ForkProcess(ForkPoolWorker-4, started daemon)>
reaping <ForkProcess(ForkPoolWorker-2, started daemon)>
reaping <ForkProcess(ForkPoolWorker-3, started daemon)>
deadpool
Traceback (most recent call last):
  File "/Users/foo/testMp.py", line 15, in <module>
    p = 1/0  # intentional bug 
ZeroDivisionError: division by zero

此时父进程挂起。

按 control-c 退出这个挂起的进程会发出键盘异常并返回终端提示符

^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Users/foo/anaconda3/envs/jupyter2/lib/python3.7/multiprocessing/util.py", line 265, in _run_finalizers
    finalizer()
  File "/Users/foo/anaconda3/envs/jupyter2/lib/python3.7/multiprocessing/util.py", line 189, in __call__
    res = self._callback(*self._args, **self._kwargs)
  File "/Users/foo/anaconda3/envs/jupyter2/lib/python3.7/multiprocessing/pool.py", line 581, in _terminate_pool
    cls._help_stuff_finish(inqueue, task_handler, len(pool))
  File "/Users/foo/anaconda3/envs/jupyter2/lib/python3.7/multiprocessing/pool.py", line 566, in _help_stuff_finish
    inqueue._rlock.acquire()
KeyboardInterrupt

如您所见,它似乎被困在“_terminate_pool”中,所以这与多进程有关

标签: python-3.xexceptionpython-multiprocessingzombie-process

解决方案


推荐阅读