該筆記是根據(jù)慕課網(wǎng)中相關視頻學習記錄么库。
視頻地址:https://www.imooc.com/learn/457
錯誤和異常的概念
概念
錯誤的概念
- 語法錯誤:代碼不符合解釋器或者編譯器語法
- 邏輯錯誤:不完整或者不合法輸入或者計算出先問題
異常的概念
- 程序遇到邏輯或者算法問題
- 運行過程中計算機錯誤(內(nèi)存不夠或者IO錯誤)
區(qū)別
錯誤
- 代碼運行前的語法或者邏輯錯誤
- 語法錯誤在執(zhí)行前修改
- 邏輯錯誤無法修改
異常
- 異常產(chǎn)生帖旨, 解釋器檢查到錯誤且認為是異常嚷炉,拋出異常
- 異常處理亡哄, 截獲異常融撞,忽略或者種植程序處理異常
常見的錯誤
- 變量未賦值直接引用 錯誤信息為: NameError
- 語法錯誤: SyntaxError
- 打開不存在文件時 錯誤信息為:IOError
- 算術運算除數(shù)為0時 錯誤信息為:ZeroDivision
- 強制類型轉(zhuǎn)換時元數(shù)據(jù)不符合轉(zhuǎn)換規(guī)則 錯誤信息為:ValueError
- 在IDE中使用 Ctrl+C 中斷程序執(zhí)行時 錯誤信息為:KeyboardInterupt
try-except 異常處理
代碼示例:
try:
print("測試代碼")
except Exception e:
print("異常處理代碼")
- try 用來捕獲 print("測試代碼") 中的異常烫堤,并且將異常就給except來處理
- except 用力啊處理異常悄晃,如果處理異常和設置捕獲異常 Exception 指向的一致,使用 print ("異常處理代碼") 來處理異常
try-except-else :處理多個異常
代碼示例
try:
f = open('1.txt', 'r')
# 讀取兩個字節(jié)的內(nèi)容
line = f.read(2)
num = int(line)
print("read the value is {}".format(num))
except IOError e:
print("catch IOError ", e)
except ValueError e:
print("catch ValueError ", e)
else:
print("it's fine, No Error")
- 上述例子中會有兩個 bug 一個是文件不存在褥蚯,另一個是讀取的數(shù)據(jù)值(有字母)無法做 int() 強制轉(zhuǎn)換挚冤。
所以通過兩個except捕獲異常- else 的作用是對無異常時的操作,看情況添加
try-finally語句
代碼示例:
try:
f = open('1.txt', 'r')
res = int(f.read())
print(res)
finally:
print("file close")
f.close()
上述代碼執(zhí)行邏輯:
- 當 try 中的代碼塊執(zhí)行無異常時赞庶,正常執(zhí)行結束后训挡,執(zhí)行 finally 中的代碼塊,打印信息和關閉文件歧强。
- 當 try 中的代碼塊執(zhí)行有異常時澜薄,會先執(zhí)行finally中的內(nèi)容,打印信息和關閉文件摊册,同時返回異常信息給python解釋器肤京。
try-finally 執(zhí)行規(guī)則:
try-finally 無論是否會檢測到異常,都會執(zhí)行finally代碼茅特。
try-finally 語句作用:
為異常處理事件提供 清理機制忘分,用來關閉文件或者釋放系統(tǒng)資源。
try-except-finally
代碼示例:
try:
f = open('1.txt', 'r')
line = f.read(2)
num = int(line)
print("read num={}".format(num))
except IOError e:
print("catch IOError", e)
except ValueError e:
print("catch ValueError", e)
finally:
try:
print("close file")
f.close()
except NameError e:
print("catch NameError",e)
上述代碼執(zhí)行邏輯
try 中的代碼塊執(zhí)行打開文件温治,讀取文件中的2個字節(jié)信息饭庞,轉(zhuǎn)換為整型并打印出結果。
- 若沒有出現(xiàn)異常熬荆,執(zhí)行玩try代碼塊之后舟山,執(zhí)行 finally 中的 try 代碼塊
- 當出現(xiàn)異常時,先執(zhí)行異常的處理函數(shù),再執(zhí)行 finally 中的代碼塊累盗,再 finally 中也有對異常的處理寒矿,主要是在,文件為被正常打開的情況下若债,關閉會出現(xiàn)異常符相,故會執(zhí)行 finally-except 中的內(nèi)容
try-except-finally 執(zhí)行規(guī)則
- 若 try 語句沒有捕獲異常,執(zhí)行完 try 代碼塊后蠢琳,執(zhí)行 finally 啊终。
- 若 try 語句捕獲到異常,首先執(zhí)行except處理錯誤傲须,然后執(zhí)行 finally 蓝牲。
try-except-else-finally語句
語法格式
try:
try_suite
except:
do_except
else:
do_else
finally:
do_finally
try-except-else-finally執(zhí)行規(guī)則
- 若 try 語句沒有捕獲異常,執(zhí)行完 try 代碼塊后泰讽,執(zhí)行 else 代碼段例衍,最后執(zhí)行 finally
- 若 try 語句捕獲異常,首先執(zhí)行 except 處理錯誤已卸,然后執(zhí)行 finally
with……as語句
語法格式
with context [as var]:
with_suite
- with 語句用來代替 try-except-finally語句佛玄,使代碼更加簡潔;
- context 表達式返回的是一個對象,該對象需要支持上下文協(xié)議
- var 用來保存 context 返回的對象,支持單個返回值為變量港谊、多個返回值為元組類型
- with_suit 使用 var 變量來對 context 返回對象進行操作
with 語句示例
with open("1.txt","r") as f:
for line in f.readlines():
print(line)
示例解釋
- open("1.txt","r") 打開文件的操作會生成一個臨時的對象
- with open("1.txt","r") as f 表示將剛剛生成的臨時對象賦值給變量 f
- with 中的代碼執(zhí)行(無異常)完成時,會 自動關閉文件惑申,若 with 代碼塊有錯誤異常具伍,則不關閉文件翅雏,被報錯中斷,故需要使用 try-except 捕捉異常人芽。
- 對于上述的自動關閉功能可以使用 print(f.closed) 來驗證望几,結果為 True 表示已關閉,F(xiàn)alse 表示未關閉
with 語句實質(zhì)是上下文管理
- 上下文管理協(xié)議: 包含方法 enter() 和 exit() , 支持該協(xié)議的對象要實現(xiàn)這兩個方法
- 上下文管理器: 定義執(zhí)行 with 語句時要在建立 運行時上下文 萤厅,負責執(zhí)行 with 語句塊上下文中的進入退出操作
- 進入上下文管理器: 調(diào)用管理器 enter()方法橄抹,如果設置 as var 語句,var 變量接受 enter() 方法 返回值
- 退出上下文管理器: 調(diào)用管理器 exit 方法惕味,對資源進行清理楼誓,對文件進行關閉。
定義一個類學習上下文管理機制:
class Mycontext(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("__enter__")
return self
def do_self(self):
print("do_self")
def __exit__(self, exc_type, exc_value, traceback):
# exc_type 參數(shù)表示 錯誤類型
# exc_value 參數(shù)表示 錯誤類型描述信息
# traceback 參數(shù)表示 出錯的堆棧信息名挥,根據(jù)堆棧信息可以知道代碼是在哪一行出了錯誤
print("__exit__")
print("Error:", exc_type, "info:", exc_value)
if __name__ == '__main__':
with Mycontext("test_context") as f:
print(f.name)
f.do_self()
返回結果:
_enter_
test_context
do_self
_exit_
Error: None info: None
該執(zhí)行結果表明 with 語句會先執(zhí)行 _enter() 方法實例化一個對象疟羹,再 _init() 初始化對象, 再執(zhí)行相關操作,最后會執(zhí)行 _exit_() 操作,這是with語句規(guī)定的榄融。
針對上述例子的異常捕獲
class Mycontext(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("__enter__")
return self
def do_self(self):
print("do_self")
a
def __exit__(self, exc_type, exc_value, traceback):
# exc_type 參數(shù)表示 錯誤類型
# exc_value 參數(shù)表示 錯誤類型描述信息
# traceback 參數(shù)表示 出錯的堆棧信息参淫,根據(jù)堆棧信息可以知道代碼是在哪一行出了錯誤
print("__exit__")
print("Error:", exc_type, "info:", exc_value)
if __name__ == '__main__':
with Mycontext("test_context") as f:
print(f.name)
f.do_self()
執(zhí)行結果
_enter_
test_context
do_self
_exit_
Error: <class 'NameError'> info: name 'a' is not defined
Traceback (most recent call last):
File "F:/脫產(chǎn)學習2017.10.27/兄弟連python/haolong/alice_code/demo/day7/test.py", line 27, in <module>
f.do_self()
File "F:/脫產(chǎn)學習2017.10.27/兄弟連python/haolong/alice_code/demo/day7/test.py", line 13, in do_self
a
NameError: name 'a' is not defined
該執(zhí)行結果表示代碼再執(zhí)行過程中出現(xiàn)在異常,會先執(zhí)行 _exit_()方法愧杯,再將異常拋出給python解釋器涎才。
應用場景
- 文件操作;
- 進程線程之間互斥對象力九,例如互斥鎖耍铜;
- 支持上下文的其他對象
raise 語句和 assert 語句
raise 語句
raise 語句用于主動拋出異常
語法格式: raise [exception[,args]]
- exception: 異常類
- args: 描述異常信息的字符串
assert 語句
斷言語句:assert語句用于檢測表達式是否為真,如果為假跌前,引發(fā) AssertionError 錯誤业扒;
語法格式:assert expression[,args]
- expression: 表達式
- args:判斷條件的描述信息,字符串
應用場景
定義函數(shù)或類中的方法舒萎,可以使用assert對傳入的參數(shù)進行格式判斷程储。在通過 try-except 對異常進行捕獲和處理
標準異常和自定義異常
標準異常:
標準異常:python 內(nèi)建異常,程序執(zhí)行前就已經(jīng)存在臂寝。
說明
- BaseException 類章鲤,所有異常都是繼承該類,若except中沒有指明異常的類型咆贬,則使用 BaseException 捕獲所有的異常
- KeyboardInterrupt 類是捕獲用戶使用 Ctrl + C 中斷程序?qū)е碌漠惓0芑玻苯永^承 BaseException 類
- Exception 類是系統(tǒng)、python解釋器異常的基類:
- 該類繼承于 BaseException 類
- 該類下還有 SyntaxError 類掏缎、NameError 類皱蹦、IOError 類、 ImportError 類等多個子類
- SystemExit 類是當 python 解釋器退出時觸發(fā)這個類眷蜈,出現(xiàn)異常
對于不明白的類沪哺,建議訪問 python 官網(wǎng),查看詳細信息
自定義異常:
- python 允許自定義異常酌儒,用于描述 python 中沒有涉及的異常情況辜妓。
- 自定義異常必須繼承 Exception 類或者Exception 類下的子類
- 自定義異常只能主動觸發(fā) raise方法觸發(fā)
自定義異常示例:
- 自定義異常:
class FileError(IOError): pass
- 產(chǎn)生自定義異常
raise FileError, "file Error"
- try-except 捕獲主動觸發(fā)的異常
try: raise FileError, "file Error" except FileError as e: print(e)