Python 无法停止\一次杀死多处理池生成的所有进程

Python 无法停止\一次杀死多处理池生成的所有进程,python,python-3.x,multiprocessing,Python,Python 3.x,Multiprocessing,当出现任何错误\异常时,我需要停止\终止所有进程。我在StackOwerflow上找到了使用psutil终止所有进程的解决方案,但有时我会遇到一个问题-当psutil终止子进程和主进程时,可能会启动新进程并继续执行代码 import psutil class MyClass: parent_pid = 0 ids_list = range(300) def main(self): self.parent_pid = os.getpid()

当出现任何错误\异常时,我需要停止\终止所有进程。我在StackOwerflow上找到了使用
psutil
终止所有进程的解决方案,但有时我会遇到一个问题-当
psutil
终止子进程和主进程时,可能会启动新进程并继续执行代码

import psutil

class MyClass:
    parent_pid = 0
    ids_list = range(300)

    def main(self):
        self.parent_pid = os.getpid()
        pool = multiprocessing.Pool(3)

        for osm_id in self.ids_list:
            pool.apply_async(self.handle_country_or_region,  
                             kwds=dict(country_id=osm_id),
                             error_callback=self.kill_proc_tree)

        pool.close()
        pool.join()

    def kill_proc_tree(self, including_parent=True):
        parent = psutil.Process(self.parent_pid)
        children = parent.children(recursive=True)

        for child in children:
            child.kill()
        psutil.wait_procs(children, timeout=5)

        if including_parent:
            parent.kill()
            parent.wait(5)

    def handle_country_or_region(self, country_id=None, queue=None):
        pass
        # here I do some task
似乎我需要终止池,而不是终止进程,但在这种情况下,如果我这样做

pool.close()
pool.terminate()
pool.join()
我的终端停止做任何事情,新线是完全空的(即没有“>>>”),什么也没有发生

理想情况下,我希望有下一个流程:如果有任何错误\异常,停止\终止所有代码执行并返回到终端中的交互式提示

有人能帮我使它正常工作吗?
我使用Python3.5和Ubuntu15.10

解决方案非常简单——将“killer”函数放在“main”中

完整代码如下所示:

class MyClass:
    ids_list = range(300)

    def main(self):
        pool = multiprocessing.Pool(3)

        def kill_pool(err_msg):
            print(err_msg)
            pool.terminate()

        for osm_id in self.ids_list:
            pool.apply_async(self.handle_country_or_region,     
                             kwds=dict(country_id=osm_id),
                             error_callback=kill_pool)

        pool.close()
        pool.join()

    def handle_country_or_region(self, country_id=None, queue=None):
        pass  # here I do some task
如果任何人需要使用
队列
,下面是代码的扩展变体,它显示了如何以正确的方式完成
队列
,从而避免出现僵尸进程:

import pickle
import os
import multiprocessing

class MyClass:
    ids_list = range(300)
    folder = os.path.join(os.getcwd(), 'app_geo')
    STOP_TOKEN = 'stop queue'

    def main(self):

        # >>> Queue part shared between processes <<<
        manager = multiprocessing.Manager()
        remove_id_queue = manager.Queue()

        remove_id_process = multiprocessing.Process(target=self.remove_id_from_file,
                                                    args=(remove_id_queue,))
        remove_id_process.start()
        # >>> End of queue part <<<

        pool = multiprocessing.Pool(3)

        def kill_pool(err_msg):
            print(err_msg)
            pool.terminate()

        for osm_id in self.ids_list:
            pool.apply_async(self.handle_country_or_region,     
                             kwds=dict(country_id=osm_id),
                             error_callback=kill_pool)

        pool.close()
        pool.join()

        # >>> Anti-zombie processes queue part <<<
        remove_id_queue.put(self.STOP_TOKEN)
        remove_id_process.join()
        manager.shutdown()
        # >>> End

    def handle_country_or_region(self, country_id=None, queue=None):
        # here I do some task
        queue.put(country_id)

    def remove_id_from_file(self, some_queue):
        while True:
            osm_id = some_queue.get()
            if osm_id == self.STOP_TOKEN:
                return
            self.ids_list.remove(osm_id)
            with open(self.folder + '/ids_list.pickle', 'wb') as f:
                pickle.dump(self.ids_list, f)
导入pickle
导入操作系统
导入多处理
类别MyClass:
ids_列表=范围(300)
folder=os.path.join(os.getcwd(),'app\u geo')
停止令牌='停止队列'
def主(自):
#>>>进程间共享的队列部分>队列结束部分>反僵尸进程队列部分>结束
def handle_country_或_region(self,country_id=None,queue=None):
#我在这里做一些工作
queue.put(国家/地区id)
def从_文件中删除_id_(自身、某些_队列):
尽管如此:
osm_id=some_queue.get()
如果osm_id==self.STOP_令牌:
返回
self.ids\u list.remove(osm\u id)
将open(self.folder+'/ids_list.pickle',wb')作为f:
pickle.dump(self.ids\u列表,f)

太糟糕了,我不能在python 2中执行此操作:(@Adi,对不起,我没有使用Python2,所以我帮不上忙。只需检查一下,在
Python2.7.12
中,我使用的所有方法都有
多处理
——如果我没记错的话,根据文档
错误回调
是为了让生活更轻松。那么,如何创建自己的
错误回调
,如图所示根据我的代码,你可以使用
池。应用异步(self.handle\u country\u或\u region,kwds=dict(country\u id=osm\u id,your\u error\u callback=kill\u pool))
定义handle\u country\u或\u region(self,country\u id=None,queue=None,your\u error\u callback=None)
。在
中,尝试调用
你的\u error\u callback()
如果出现错误。我更喜欢使用Event()对象作为关闭的标志(退出无限循环),在您的方法中,您只在队列中放置了1颗“有毒药丸”,而这不正是您(仅)服用的吗第一个可用的进程让其他进程仍然活着?@LohmarASHAR,我现在不能确定,因为那是很久以前的事了,但我记得所有进程都被终止了,这正是我所需要的。我将阅读Event(),谢谢。