try …except…else 语句
是处理异常公式, try 是有可能抛异常的代码块, except 抓取异常的类型, else 是指当没有抓到抛错,就运行这块代码。请看下下边的例子:
代码语言:javascript复制try:
print("抓取的有可能的代码块")
raise IOError
except IOError as e:
print("except IOError")
except OSError as e:
print("except OSError")
else:
print("other erro")
finally:
print("i am finally")
#打印结果:
抓取的有可能的代码块
except IOError
i am finally
从结果来看 走的路线是: try(按照raise 的error 找except)>找到except并执行except代码块>执行finally语句块 如果没有抛错走的路线是: try 没有error>走else 语句>finally 看来不管有没有错误, finally 语句一定会执行到。 在用到finally 要注意他会覆盖 except or else 的返回值。
代码语言:javascript复制def try_list():
try:
print("抓取的有可能的代码块")
raise OSError
return 1
except IOError as e:
print("except IOError")
return 2
except OSError as e:
print("except OSError")
return 3
else:
print("other erro")
return 4
finally:
print("i am finally")
return 5
print(try_list())
#打印结果
抓取的有可能的代码块
except IOError
i am finally
5
从打印的结果 ,他覆盖了 return 3。 如果走else路线同样return 的4 也会被覆盖, 自己试试下。 那小伙伴有疑问 什么情况下使用 finally 呢 答案: 是在释放资源的时候, 看下边的例子。
代码语言:javascript复制def try_list():
try:
fp=open("Test。txt")
raise OSError
fp.close()
except IOError as e:
fp.close()
except OSError as e:
fp.close()
print("except OSError")
else:
print("other erro")
fp.close()
大家看了 吗, 只要有流程的分支的地方一定要加上这个 fp.close(), 如果再加分支,还需要再加这个close 函数。 有没有更好的解决方法吗? 答案就是 用finally。请看下边的代码:
代码语言:javascript复制def try_list():
try:
fp=open("Test。txt")
raise OSError
except IOError as e:
except OSError as e:
print("except OSError")
else:
print("other erro")
finally:
fp.close()
大家看看是不是很神奇, 资源的释放不光是文件的关闭,还有socket 连接,数据库的连接。
上边的内容只是复习下异常处理的内容, 下边才是重头戏 with上下文管理器 。
with上下文管理器
with上下文管理器协议包括两个魔法函数 1.__enter__2.exit 用实例来解释下这两个魔法函数
代码语言:javascript复制class Person:
def __enter__(self): #获取资源
print("enter")
def __exit__(self, exc_type, exc_val, exc_tb): #释放资源
print("exit")
def said(self):
print("said")
with Person() as P:
P.said()
打印结果是: enter Traceback (most recent call last): exit File “C:/Users/tengfei/PycharmProjects/test1/alert.py”, line 12, in P.said() AttributeError: ‘NoneType’ object has no attribute ‘said’
根据提示我们就知道了, 我们实例化是“NoneType” 类型,意思就是空的对象。
原因是 因为我们在获取资源(enter)没有返回值,所以默认返回的是空。 我们加上 返回值 就可以运行成功了如下:
代码语言:javascript复制class Person:
def __enter__(self): #并没有调用,也会运行这个函数
print("enter")
# return self
def __exit__(self, exc_type, exc_val, exc_tb): #并没有调用,也会运行这个函数
print("exit")
def said(self):
print("said")
with Person() as P:
P.said()
打印结果: enter #并没有调用,也会运行这个函数 said exit #并没有调用,也会运行这个函数
总结: 上下文管理器协议 是用with 进行调用,默认调用了 enter 和 exit 两个魔法函数。 with是对try…expect…finally语法的一种简化,并且提供了对于异常非常好的处理方式。 根据实际需要应用在不同的场景。