zoukankan      html  css  js  c++  java
  • Python多线程捕获子线程的异常,并退出主进程。

    自己在项目的开发中,一般能避免在单个进程中使用多线程就尽量把每个线程包装成独立的进程执行,通过socket或者一些中间件比如redis进行通讯,工作,协调。

    但有时候必须涉及到多线程操作,而且碰到的情况中,多个线程必须协调全部正常工作才能执行逻辑,但子线程有着自己的栈区,报错了并不影响其它的线程,导致整个进程无法退出。

    我当时想到的有两种思路,一种是多个线程间进行通讯或者一个全局变量的标记,当报错的时候,就修改这个标记,所有的子线程定时去查询这个标记,但感觉这个思路的拓展性太差,而且每个子线程需要主动定期查询或者通讯,太麻烦了。

    后面一种就是我准备上代码的思路, 将所有的子线程设计成守护线程,主线程循环查询子线程的状态值,当发现任意的子线程状态异常,获取该子线程的异常对象,并上浮,退出主线程,导致所有的子线程退出。

    import threading, traceback
    import time
    
    class ExcThread(threading.Thread):
        def __init__(self, call_obj, *args, **kwargs):
            super(ExcThread, self).__init__(*args, **kwargs)
            self.callable_obj = call_obj
            # 自己设置的退出状态值
            self.exit_code = 0
            self.exception = None
            self.exc_traceback = ''
            
            # 主动设置为守护线程,必须条件
            self.setDaemon(True)
    
        def run(self):
            try:
                self._run()
            except Exception as e:
                self.exit_code = 1
                # 存储异常对象保存在实例对象中
                self.exception = e
                self.exc_traceback = traceback.format_exc()
    
        def _run(self):
            try:
                self.callable_obj(*self._args, **self._kwargs)
            except Exception as e:
                raise e
    
    def t_func(name, age=18):
        while 1:
            print(name, age)
            time.sleep(3)
            if age == 1:
                raise Exception('hee')
    
    
    # 生成一份子线程列表对象,用于主线程轮询检查使用
    def start_child_thread():
        thread_task_list = []
        for i in range(3):
            f = ExcThread(call_obj=t_func, args=('sidian',), kwargs={'age': i})
            f.start()
            thread_task_list.append(f)
        return thread_task_list
    
    
    def check_thread():
        t_list = start_child_thread()
        while 1:
            for task in t_list:
                if not task.is_alive():
                    raise task.exception
                time.sleep(1)
    
    
    if __name__ == '__main__':
        check_thread()
    

      

  • 相关阅读:
    TCP/IP(三)数据链路层~2
    TCP/IP(三)数据链路层~1
    TCP/IP(二)物理层详解
    Maven(六)之依赖管理
    RAID : 独立磁盘冗余阵列(Redundant Array of Independent Disks)
    Oracle启动两个监听
    Oracle服务器修改IP后
    su: cannot set user id: Resource temporarily unavailable
    hadoop报错:java.io.IOException(java.net.ConnectException: Call From xxx/xxx to xxx:10020 failed on connection exception: java.net.ConnectException: 拒绝连接
    spring boot 实现mybatis拦截器
  • 原文地址:https://www.cnblogs.com/sidianok/p/15726845.html
Copyright © 2011-2022 走看看