异常处理的通常处理方法浅见

很多编程语言有异常处理的语法,有时用起来非常方便。不过什么时候使用,该捕获什么异常,捕获后如何处理,什么时候扩散此异常,尤其是在函数,类,模块,主循环/函数中分别如何处理,有时候很费思量。这里以python为例,总结一下个人想法,抛砖引玉。

基本语法

异常处理的语法用好了非常方便。一个原因是和日常思考的过程,以及定义需求的思路类似。通常我们梳理需求,或者写功能时先写正常功能流程的需求,然后梳理异常情况下的需求,对应到代码就是正常功能代码和异常处理的代码。而不用正常流程的每个函数调用都判断一下返回值,处理一下异常情况。

基本语法如下:

try:

expression

expression

except ErrorA:

handle_ErrorA

except (ErrorB, ErrorC) as err:

handle_ErrorBC

except:

expression run on any other exceptions.

else:

expression run on no exception

finally:

expression run anyway

什么时候捕获异常

个人倾向于在一段处理逻辑后针对不同的异常进行处理,保障程序异常情况下的正常执行。处理逻辑的范围,要看异常处理代码的恢复范围。为了代码可读性,不建议太小,比如一个函数一个异常处理。比如:

def handle_data():

Open database

Read data from the database

Handle the data

Close the database

可以在这段功能外围整体进行异常处理,而不用每个处理分别进行异常处理。

也不建议外层的函数中处理几层以内的函数中的异常;

比如处理数据中调用了验证的函数,验证函数可能从另一个数据源获取数据。验证函数从另一个数据源获取数据的异常就应该在内层函数中处理,而不是在外层函数中处理。

跨越类或模块建议在把内部实现过程中遇到的异常封装在类/模块内部,统一返回这个类/模块的异常。比如:一个读取数据的模块,内部使用远程数据库读取数据,读取过程中可能会产生socket的异常,这种异常就建议封装在内部,进行重连或者反馈数据无法获得。而不是抛出socket的异常,让外部使用的代码捕获它。外部代码即使捕获到也无法恢复这种异常情况。

建议不要在内层函数中捕获所有的异常。因为没有预期的恢复处理,会深藏bug或引起不可预期的行为。除非是长期运行的服务类程序,可以考虑在主循环中捕获所有的异常。即使捕获所有异常也建议输出异常信息以便排查。

异常的处理

尽量根据具体的异常处理,使程序能从异常中恢复继续正常运行。通常的情况是对熟悉的几种异常进行了处理。逻辑上每个系统调用都可能出错,我们不对每个函数调用做异常处理,并不代表这个函数不会发生异常。比如上面的handle_data函数,如果数据库打不开如何处理?持续打不开如何处理?写数据库时报数据错误如何处理?

另外我们对未处理的异常可以输出必要的信息。比如一个服务程序通常会有一个主循环,通常会捕获所有的其他异常,记录后,继续提供服务。sys.exc_info()可以获得异常的类,异常的参数和一个堆栈的对象。traceback.format_exc()可以获得整个对战。下面是个示例代码:

try:

raise Exception('spam', 'eggs')

except:

print(‘Except[%s]’ % sys.exc_info())

print('Exception[%s]' % traceback.format_exc())

显示如下:

Exception[(, Exception('spam', 'eggs'), )]

Exception[Traceback (most recent call last):

File “./test.py”, line 30, in test

raise Exception('spam', 'eggs')

Exception: ('spam', 'eggs')

]

不要忘记在异常处理中释放异常发生前分配的资源。通常在finally中处理,或者用with语句。

抛出异常

自己抛出的异常建议有自己的捕获此异常的代码处理。如果一系列自己定义的异常,可以定义自己的异常类。

有时候抛出异常和返回错误值,都可以。抛异常性能略差。个人推荐经常可能发生的,尽量用返回值。

其他

异常处理机制如果使用得当会极大的方便编程实现。上面的提到的一些建议并非普遍适用,有些场景可能其他方式更有效率。需要在熟悉后逐渐总结。

欢迎反馈,关注,转发,谢谢!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180701G0ZYTZ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券