美文网首页
异常处理并记录日志(多线程情况)

异常处理并记录日志(多线程情况)

作者: VChao | 来源:发表于2020-07-16 16:54 被阅读0次

    2020/07/16 -

    引言

    正常情况下,经常会让应用后台运行,这种情况下,不可避免地就会出现异常,那么出现异常之后,同时还需要对异常进行定位,这样能够保证后续的日志查看的时候更方便定位异常,从而修改代码。

    异常的传播途径

    首先,异常在发生之后,如果不及时在发声位置进行处理,那么他会逐层往上传播,直到有某层能够处理这部分异常的时候,就不再往上传播,当然可以手动引起异常,raise。
    这里引发的问题就是,应该再哪一层进行异常的处理呢?我记得我之前的时候看过一篇文章,就是说在最接近异常的地方将异常处理完毕是最好的,这样能够保证上层的逻辑越清晰。

    多线程的异常处理

    我这里遇到的问题就是,因为需要多线程工作,虽然出现了异常,这可能是某个参数导致的,但是我希望其他的线程依然能进行工作。当前使用的是线程池的形式(每次一个程序结束,就启动这个线程而不是向队列一样取数据),那么就需要在每个函数启动的地方添加异常处理。
    但是正常情况下,线程池的工作方式,在异常出现了之后,他推出,并不影响其他的线程工作。他们只是从一个可迭代的列表中进行进行工作而已。
    但是我这里的出现的问题好像是,这个程序没有完整的推出,最后导致还有很多和mysql的连接。这个我就有带你不是很理解了。而且,同时,这个定时任务的进程也没有推出。。。最后累积了好几个线程。

    然后我测试了一些方案,也没有复现出来这种问题。当时是因为使用了django的定时任务,然后他最后在我定义的logging日志文件中还是打印出来了异常信息。
    但是我找不出为什么会发生这种异常的原因。

    反正情况就是,因为需要连接数据库,然后这个数据库的连接最后就没有跟mysql断开,可以通过数据库的查询命令看到。
    然后最后这个程序也没有退出。

    注意这里的几个特点:
    1)程序由django的定时任务驱动
    2)即使报错,其实也不影响整个程序的分析,只是这个线程挂了而已,不该影响整个程序。
    3)程序中存在某种开启的Tcp连接这种东西,虽然不是我显式开启的。

    异常处理方式

    异常处理的方式呢,我感觉,只要你觉的这个程序可能是异常,那就就一定要打印一些信息,以前的时候,图方便,都直接pass了,而且还是全异常都直接关闭了,这就非常尴尬了,有时候还会造成非常出乎意料的结果,就是报错了自己也不知道。

    1)利用traceback库

    import traceback
    try:
       print(1/0)
    except Exception:
       traceback.print_exc()
    
    traceback.print_exc() #直接打印异常
    traceback.format_exc()#返回字符串
    traceback.print_exc(file=open(‘log.txt’,’a+’))
    

    2)利用logging的方式 python logging日志捕获代码异常(traceback)

    更好的处理方式

    对于异常代码的处理形式呢,更好的方式其实应该是使用装饰器的形式(这种情况适用于很多函数可能都是同样的异常处理机制)。

    def exception_handler(func):
       def inner_function(*args, **kwargs):
           try:
               func(*args, **kwargs)
           except TypeError:
               print(f"{func.__name__} only takes numbers as the argument")
       return inner_function
    
    
    @exception_handler
    def area_square(length):
       print(length * length)
    
    
    @exception_handler
    def area_circle(radius):
       print(3.14 * radius * radius)
    
    
    @exception_handler
    def area_rectangle(length, breadth):
       print(length * breadth)
    
    
    area_square(2)
    area_circle(2)
    area_rectangle(2, 4)
    area_square("some_str")
    area_circle("some_other_str")
    area_rectangle("some_other_rectangle")
    

    代码来自(handling-exceptions-in-python-a-cleaner-way-using-decorators

    然后我又去翻了翻ss的代码,在我印象中他就这么个逻辑来处理异常的。打开了看了,果然,而且,他的处理方式更加复杂, 应该是能应付更多的异常形式。。

    问题

    我这里发生了一个问题,就是不知道为什么, 他没有报错呢?就是我开的一个线程,他有错,但是没有报错,这个东西没有停止。。。我非常纳闷。。
    找到原因了,这个程序也是我在调试django的时候出现的, 整个程序是这么回事,每次docker启动之后,就首先先进行一次定时任务,不管到没到时间,这个程序是在django启动之前启动的,利用&来后台运行,最后的确打印了错误,是在整个这个python结束了之后打印,而且是打印在了docker的日志中。。。
    就感觉挺纳闷的。。。

    相关文章

      网友评论

          本文标题:异常处理并记录日志(多线程情况)

          本文链接:https://www.haomeiwen.com/subject/dnxphktx.html