1.異常簡介
異常即是一個事件,該事件會在程序執(zhí)行過程中發(fā)生,影響了程序的正常執(zhí)行豁遭。
一般情況下拴还,在Python無法正常處理程序時就會發(fā)生一個異常。
異常是Python對象鸦难,表示一個錯誤栖榨。
當(dāng)Python腳本發(fā)生異常時我們需要捕獲處理它,否則程序會終止執(zhí)行明刷。
看如下示例:
說明:
打開一個不存在的文件123.txt婴栽,當(dāng)找不到123.txt文件時,就會拋出給我們一個IOError類型的錯誤辈末,No such file or directory:123.txt(沒有123.txt這樣的文件或目錄)
異常:
當(dāng)Python檢測到一個錯誤時愚争,解釋器就無法繼續(xù)執(zhí)行了映皆,反而出現(xiàn)了一些錯誤的提示,這就是所謂的"異常"
2.捕獲異常
1.捕獲異常try...except...
運行結(jié)果:
說明:
·此程序看不到任何錯誤轰枝,因為用except捕獲到了IOError異常捅彻,并添加了處理的方法
·pass表示實現(xiàn)了相應(yīng)的實現(xiàn),但什么也不做鞍陨;如果把pass改為print語句步淹,那么就會輸出其他信息
小總結(jié):
·把可能出現(xiàn)問題的代碼,放在try中
·把處理異常的代碼诚撵,放在except中
2.python異常處理
BaseException ? ? ? ? ? ?所有異常的基類
SystemExit ? ? ? ? ? ? ? ? ?解釋器請求退出
KeyboardInterrupt ? ? ? ?用戶中斷執(zhí)行(通常是輸入^C)
Exception ? ? ? ? ? ? ? ? ? ?常規(guī)錯誤的基類
StopIteration ? ? ? ? ? ? ? ?迭代器沒有更多的值
GeneratorExit ? ? ? ? ? ? ? 生成器(generator)發(fā)生異常來通知退出
StandardError ? ? ? ? ? ? ? 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類
ArithmeticError ? ? ? ? ? ? ?所有數(shù)值計算錯誤的基類
FloatingPointError ? ? ? ? ?浮點計算錯誤
OverflowError ? ? ? ? ? ? ? ?數(shù)值運算超出最大限制
ZeroDivisionError ? ? ? ? ? ?除(或取模)零 (所有數(shù)據(jù)類型)
AssertionError ? ? ? ? ? ? ? ? 斷言語句失敗
AttributeError ? ? ? ? ? ? ? ? ?對象沒有這個屬性
EOFError ? ? ? ? ? ? ? ? ? ? ? ?沒有內(nèi)建輸入,到達(dá)EOF 標(biāo)記
EnvironmentError ? ? ? ? ? ? 操作系統(tǒng)錯誤的基類
IOError ? ? ? ? ? ? ? ? ? ? ? ? ? 輸入/輸出操作失敗
OSError ? ? ? ? ? ? ? ? ? ? ? ? ?操作系統(tǒng)錯誤
WindowsError ? ? ? ? ? ? ? ? 系統(tǒng)調(diào)用失敗
ImportError ? ? ? ? ? ? ? ? ? ? 導(dǎo)入模塊/對象失敗
LookupError ? ? ? ? ? ? ? ? ? ?無效數(shù)據(jù)查詢的基類
IndexError ? ? ? ? ? ? ? ? ? ? ? 序列中沒有此索引(index)
KeyError ? ? ? ? ? ? ? ? ? ? ? ? 映射中沒有這個鍵
MemoryError ? ? ? ? ? ? ? ? ? 內(nèi)存溢出錯誤(對于Python 解釋器不是致命的)
NameError ? ? ? ? ? ? ? ? ? ? ? 未聲明/初始化對象 (沒有屬性)
UnboundLocalError ? ? ? ? ? 訪問未初始化的本地變量
ReferenceError ? ? ? ? ? ? ? ? 弱引用(Weak reference)試圖訪問已經(jīng)垃圾回收了的對象
RuntimeError ? ? ? ? ? ? ? ? ? ? 一般的運行時錯誤
NotImplementedError ? ? ? ? 尚未實現(xiàn)的方法
SyntaxErrorPython ? ? ? ? ? ? 語法錯誤
IndentationError ? ? ? ? ? ? ? ? 縮進(jìn)錯誤
TabErrorTab ? ? ? ? ? ? ? ? ? ? 和空格混用
SystemError ? ? ? ? ? ? ? ? ? ? ?一般的解釋器系統(tǒng)錯誤
TypeError ? ? ? ? ? ? ? ? ? ? ? ? ?對類型無效的操作
ValueError ? ? ? ? ? ? ? ? ? ? ? ? 傳入無效的參數(shù)
UnicodeErrorUnicode ? ? ? ? ? 相關(guān)的錯誤
UnicodeDecodeErrorUnicode ?解碼時的錯誤
UnicodeEncodeErrorUnicode ?編碼時錯誤
UnicodeTranslateErrorUnicode 轉(zhuǎn)換時錯誤
Warning ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?警告的基類
DeprecationWarning ? ? ? ? ? ? ? ?關(guān)于被棄用的特征的警告
FutureWarning ? ? ? ? ? ? ? ? ? ? ? ? 關(guān)于構(gòu)造將來語義會有改變的警告
OverflowWarning ? ? ? ? ? ? ? ? ? ? 舊的關(guān)于自動提升為長整型(long)的警告
PendingDeprecationWarning ? ? 關(guān)于特性將會被廢棄的警告
RuntimeWarning ? ? ? ? ? ? ? ? ? ? ?可疑的運行時行為(runtime behavior)的警告
SyntaxWarning ? ? ? ? ? ? ? ? ? ? ? ?可疑的語法的警告
UserWarning ? ? ? ? ? ? ? ? ? ? ? ? ? 用戶代碼生成的警告
3.except捕獲多個異常
4.獲取異常的信息描述
5.捕獲所有異常
6.else
在if中缭裆,它的作用是當(dāng)條件不滿足時執(zhí)行的實行;同樣在try...except...中也是如此寿烟,即如果沒有捕獲到異常澈驼,那么就執(zhí)行else中的事情
7.try...finally...
try...finally...語句用來表達(dá)這樣的情況:
在程序中,如果一個段代碼必須要執(zhí)行筛武,即無論異常是否產(chǎn)生都要執(zhí)行缝其,那么此時就需要使用finally。 比如文件關(guān)閉徘六,釋放鎖内边,把數(shù)據(jù)庫連接返還給連接池等
說明:
test.txt文件中每一行數(shù)據(jù)打印,但是我有意在每打印一行之前用time.sleep方法暫停2秒鐘待锈。這樣做的原因是讓程序運行得慢一些漠其。在程序運行的時候,按Ctrl+c中斷(取消)程序炉擅。
我們可以觀察到KeyboardInterrupt異常被觸發(fā)辉懒,程序退出。但是在程序退出之前谍失,finally從句仍然被執(zhí)行眶俩,把文件關(guān)閉。
3.異常的傳遞
1.try嵌套中
2.函數(shù)嵌套調(diào)用中
運行結(jié)果:
總結(jié):
·如果try嵌套快鱼,那么如果里面的try沒有捕獲到這個異常颠印,那么外面的try會接收到這個異常,然后進(jìn)行處理抹竹,如果外邊的try依然沒有捕獲到线罕,那么再進(jìn)行傳遞。窃判。钞楼。
·如果一個異常是在一個函數(shù)中產(chǎn)生的,例如函數(shù)A---->函數(shù)B---->函數(shù)C,而異常是在函數(shù)C中產(chǎn)生的袄琳,那么如果函數(shù)C中沒有對這個異常進(jìn)行處理询件,那么這個異常會傳遞到函數(shù)B中燃乍,如果函數(shù)B有異常處理那么就會按照函數(shù)B的處理方式進(jìn)行執(zhí)行;如果函數(shù)B也沒有異常處理宛琅,那么這個異常會繼續(xù)傳遞刻蟹,以此類推。嘿辟。舆瘪。如果所有的函數(shù)都沒有處理,那么此時就會進(jìn)行異常的默認(rèn)處理红伦,即通常見到的那樣
·注意觀察上圖中英古,當(dāng)調(diào)用test3函數(shù)時,在test1函數(shù)內(nèi)部產(chǎn)生了異常色建,此異常被傳遞到test3函數(shù)中完成了異常處理哺呜,而當(dāng)異常處理完后舌缤,并沒有返回到函數(shù)test1中進(jìn)行執(zhí)行箕戳,而是在函數(shù)test3中繼續(xù)執(zhí)行
4.拋出自定義的異常
你可以用raise語句來引發(fā)一個異常。異常/錯誤對象必須有一個名字国撵,且它們應(yīng)是Error或Exception類的子類
1.
2.
3.
注意
以上程序中陵吸,關(guān)于代碼#super().__init__()的說明
這一行代碼,可以調(diào)用也可以不調(diào)用介牙,建議調(diào)用壮虫,因為__init__方法往往是用來對創(chuàng)建完的對象進(jìn)行初始化工作,如果在子類中重寫了父類的__init__方法环础,即意味著父類中的很多初始化工作沒有做囚似,這樣就不保證程序的穩(wěn)定了,所以在以后的開發(fā)中线得,如果重寫了父類的__init__方法饶唤,最好是先調(diào)用父類的這個方法,然后再添加自己的功能