try …except…else 語句
是處理異常公式, try 是有可能抛異常的代碼塊, except 抓取異常的類型, else 是指當沒有抓到抛錯,就運作這塊代碼。請看下下邊的例子:
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 的傳回值。
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 呢
答案: 是在釋放資源的時候,
看下邊的例子。
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。請看下邊的代碼:
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
用執行個體來解釋下這兩個魔法函數
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)沒有傳回值,是以預設傳回的是空。
我們加上 傳回值 就可以運作成功了如下:
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文法的一種簡化,并且提供了對于異常非常好的處理方式。
根據實際需要應用在不同的場景。