「异常」处理的时候,你用过这些技巧吗?

640


640


本文字数:2095 字

阅读本文大概需要:6 分钟


00.写在之前


当 Python 检测到一个错误时,解释器就无法继续执行下去,于是抛出提示信息,即为「异常」。程序出现了异常,就要做「异常处理」。


Python 的异常在使用上很简单,因此很多人处理异常的时候也相当简单粗暴,随着性子用 try...except...,心情好了可能带上 else 或者 finally,感觉差不多就行,完全不考虑之后会不会再有其它的异常或者某些玄学的事情发生。


「异常」背后是有很多技巧存在的,并不是想象中的随感觉乱用,接下来我就分享一下我所知道的技巧,让你在碰到异常的时候能得心应手的处理。


 01.except 技巧


使用 Python 可以选择捕获哪些异常,在这里必须要注意的是不要涵盖的范围太广,即要尽量避免 except 后面为空,最好是要带东西的。except 后面如果什么也不带,它会捕捉 try 代码块中代码执行时所出现的每个异常。


虽然后面什么也不带在大多数情况下得到的也是我们想要的结果,但是代码块中如果是个嵌套结构的话,它可能会破坏嵌套结构中的 try 得到它想要的结果。比如下面这种情况:


def func(): try: # do something1 except: # do something2try: func()except NameError: # do something3
try:
# do something1
except:
# do something2

try:
func()
except NameError:
# do something3

 

比如上面的代码,如果在 something1 处出现了 NameError,那么所有的异常都会被 something2 处捕获到,程序就此停掉,而正常情况下应该捕获到 NameError 的 something3 处则什么异常也没有。


上面只是说了一个简单的情况,因为 Python 运行在个人电脑中,可能有时候内存错误,系统莫名退出这种异常也会被捕捉到,而现实情况是这些和我们当前的运行的程序一毛钱关系也没有。


可能这时候有人会想到 Exception 这个内置异常类,但实际情况是 except Exception 比 except 后面什么也不带好不到哪里去,大概也只是好在系统退出这种异常 Exception 不会捕捉。


那该如何使用 except 呢?


那就是尽量让 except 后面具体化,例如上面代码中的 except NameError: ,意图明确,不会拦截无关的事件。虽然只写一个 except 很方便,但有时候追求方便恰恰就是产生麻烦的源头。


02.类异常


在上一节我说尽量要让 except 后面具体化,在列出特定的异常时,就只是去捕捉实际列出来的事件。但是现在又有这么一个问题,当程序简单的时候还好说,但是随着程序变得复杂起来,肯定还会出现别的异常,这样的话我们就只能回头去找,然后再把新出现的异常加进去:


try: # do something1except (NameError,KeyError): # do something2else: # do something3
# do something1
except (NameError,KeyError):
# do something2
else:
# do something3


上面的代码中是把 NameError 和 KeyError 看作是正常的情况,把其它的视为错误。如果在之后的发展中增加了 TypeError ,程序就会把它视为错误并且对它进行处理,除非把它加进去:


try:# do something1except (NameError,KeyError,TypeError):# do something2else:# do something3# do something1
except (NameError,KeyError,TypeError):
# do something2
else:
# do something3


但是这样每次过去添加也太麻烦了,当代码量巨大的时候,定位然后再添加是又费时又费力,所以这个时候我们可以使用「类异常」。类异常是由超类关系进行匹配,只要 except 子句列举了异常的类或其它超类名,出现的异常就会匹配这个子句:


class BaseError(Exception): # return all errorclass IsNameError(BaseError): # return NameErrorclass IsKeyError(BaseError): # return KeyErrortry: # do something1except BaseError: # do something2else: # do something3
# return all error
class IsNameError(BaseError):
# return NameError
class IsKeyError(BaseError):
# return KeyError

try:
# do something1
except BaseError:
# do something2
else:
# do something3


当随着出现新的异常的时候,只需要再扩展响应的子类即可:


class BaseError(Exception): # return all errorclass IsNameError(BaseError): # return NameErrorclass IsKeyError(BaseError): # return IsKeyErrorclass IsTypeError(BaseError): # return IsTypeErrortry: # do something1except BaseError: # do something2else: # do something3
# return all error
class IsNameError(BaseError):
# return NameError
class IsKeyError(BaseError):
# return IsKeyError
class IsTypeError(BaseError):
# return IsTypeError

try:
# do something1
except BaseError:
# do something2
else:
# do something3


这样就不用再手动扩展 except 后面的异常列表,BaseError 变成了可扩展的异常分类。


以上。


如果觉得对你有所帮助,请帮忙点一下右下角的「在看」呦 smiley_66.png




640?wx_fmt=gif

我们都知道的「字典」,到底可以用来做什么?

曾经,我被这些陷阱坑的找不着北...

直到面试被问到什么是「共享引用」,我才发现对于它的一无所知...

浅谈动态类型领域中 Python 的变量、对象以及引用。





640?wx_fmt=jpeg

?扫描上方二维码即可关注




发布了608 篇原创文章 · 获赞 5913 · 访问量 88万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 酷酷鲨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览