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

2020-07-16  本文已影响0人  VChao

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的日志中。。。
就感觉挺纳闷的。。。

上一篇下一篇

猜你喜欢

热点阅读