掉進懸崖的小白,學習python異常處理,做簡單總結
什麼是異常?
異常實際上是程序中錯誤導致中斷了正常的指令流的一種事件.
和傳統的方法比較異常的優點:
1.把錯誤代碼從常規代碼中分離出來
2.把錯誤傳播給調用堆棧
3. 按錯誤類型和錯誤差別分類
4. 系統提供了對於一些無法預測的錯誤的捕獲和處理
什麼情況下使用異常機制?
1.當方法因爲自身無法控制的原因而不能完成其任務
文件不存在,網絡連接無法建立……
2.處理在引入模塊中拋出的異常
3.在大的項目中採用統一的方式處理異常時
如編寫一個文字處理器
4.異常應該是不經常發生但卻可能發生的故障
一定發生的事件不應該用異常機制來處理
5.異常處理用於使系統從故障中恢復
提示信息/不產生無效的結果/釋放資源
注意事項:
1.不同的異常處理策略
關鍵性應用(處理所有異常)
實驗軟件(可以忽略許多異常)
2.終止程序會導致資源泄漏,利用異常處理釋放資源
3.儘可能近地處理異常,這樣程序清晰易讀
4.能在局部處理的錯誤不要使用異常機制
異常機制的處理比正常處理效率低
處理機制
捕獲並處理異常
try:
# 接受監視的程序塊,在此區域內發生的異常,由except中指定的程序處理
#不能有其它語句分隔
except 要處理的異常種類1 as 標識符1:
# 處理異常
except 要處理的異常種類2 as 標識符2:
# 處理異常
…
或者
except (異常種類1, 異常種類2…) as 標識符…:
# 處理異常
或者
except:
# 上面未捕獲的處理異常
else:
# 未監視到異常時執行的代碼
finally:
# 有無異常均會執行的代碼
try語句:異常監視塊
作用:監視該代碼塊是否有異常發生,若有異常,產生異常對象並拋出
except語句:異常處理代碼塊
作用:捕捉try語句中拋出的異常,並按照代碼塊中的語句處理
格式:標識符主要用於解析異常對象
except 要處理的異常種類 as 標識符:
except (異常種類1, 異常種類2…) as 標識符…:
注意:
1.每個try語句必須伴隨1-n個except語句
2.異常總是由距離產生異常最近的匹配except代碼段處理
3.try-except可以嵌套使用
4.匹配的except執行完畢後,同級的except將被忽略
5.先except小的再except老的
6.整個執行流程中若無except處理 程序中斷!
7.except的類型應儘量精確
8.請注意你調用的方法是否有可能拋出異常
9.except中也可能產生異常 會拋給嵌套的上一級處理
10.永遠不要except中吞掉異常,否則在系統發生異常時,你永遠不知道到底發生了什麼:
推薦:
except BaseException:
# 處理異常的語句
raise #再次將異常拋出
11.try-except機制不該被用於流程控制,異常情形應該是很稀少的,而不是經常性的
else
等同於for…else和while…else
在不發生異常時執行的語句塊
一定會執行的程序塊—finally
異常處理的統一出口
finally:
# 不論發生什麼異常(或者不發生任何異常),都要執行的部分;
finally:
1.捕獲異常的最後一步是通過finally語句爲異常處理提供一個統一的出口,使得在控制流程轉到程序的其他部分以前,能夠對程序的狀態作統一的管理。
2.無論try所指定的程序塊中是否拋出異常,也無論except語句的異常類型是否與所拋棄的異常的類型一致,finally所指定的代碼都要被執行,它提供了統一的出口。
3.通常在finally語句中可以進行資源的清除工作,如關閉打開的文件、刪除臨時文件等。
finally和return的關係:
1.當try和except中有return時,finally仍然會執行;
2.finally是在return後面的表達式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值保存起來,不管finally中的代碼如何修改,返回的值都不會改變,仍然是之前保存的值),所以函數返回值是在finally執行前確定的;
異常分類
- BaseException # 所有異常的父類
- SystemExit # 由sys.exit()拋出的異常
- KeyBoardInterrupt # 通常由ctrl+c或者Delete拋出的異常
- GeneratorExit # 生成器(generator)發生異常來通知退出
- Exception # 常規異常基類
- StopIteration # 迭代器沒有更多的值
- StopAsyncIteration # 由異步迭代的__anext__()拋出的異常
- ArithmeticError # 各種算數錯誤引起的異常
- FloatingPointError # 浮點數操作錯誤
- OverflowError # 結果超出範圍
- ZeroDivisionError # 0爲除數異常
- AssertionError # assert錯誤異常
- AttributeError # 屬性引用異常
- BufferError # 緩存錯誤
- EOFError # 讀不到數據
- ImportError # import錯誤
- ModuleNotFoundError # 找不到模塊
- LookupError # 由索引和key值引起的異常
- IndexError # 索引錯誤
- KeyError # 字典key值錯誤
- MemortError # 內存溢出異常
- NameError # 本地和全局找不到變量名
- UnboundLocalError # 局部變量沒有賦值
- OSError # system錯誤
- BlockingIOError # 調用阻塞異常錯誤
- ChildProcessError # 子進程
- ConnectionError # 連接
- BrokenPipeError # 管道讀寫異常
- ConnectionAbortedError # 連接失敗
- ConnectionRefusedError # 連接拒絕
- ConnectionResetError # 連接重置
- FileExistsError # 創建文件和文件夾錯誤
- FileNotFoundError # 文件未找到
- InterruptedError # 中斷錯誤
- IsADirectoryError # 文件操作用在文件夾上
- NotADirectoryError # 不是文件夾
- PermissionError # 權限
- ProcessLookupError # 進程不存在
- TimeoutError # 超時
- ReferenceError # 試圖訪問已經垃圾回收的對象異常
- RuntimeError #
- NotImplementedError # 未實現抽象方法異常
- RecursionError # 超出最大遞歸深度
- SyntaxError # 語法錯誤
- IndentationError # 縮進錯誤
- TabError # Tab 和空格混用
- IndentationError # 縮進錯誤
- SystemError # 解釋器中斷
- TypeError # 對類型無效的操作
- ValueError # 賦值錯誤
- UnicodeError # Unicode 相關的錯誤
- UnicodeEncodeError # unicode編碼錯誤
- UnicodeDecodeError # unicode解碼錯誤
- UnicodeTranslateError # unicode轉換錯誤
- UnicodeError # Unicode 相關的錯誤
- Warning # 警告的基類
- DeprecationWarning # 關於被棄用的特徵的警告
- PendingDeprecationWarning # 表明此操作將來會被棄用
- UserWarning # 用戶代碼生成的警告
- SyntaxWarning # 可疑的語法的警告
- RuntimeWarning # 可疑的運行時行爲警告
- FutureWarning # 關於構造將來語義會有改變的警告
- ImportWarning # 導入警告
- UnicodeWarning # unicode相關警告
- BytesWarning # 字節相關警告
- ResourceWarning # 資源使用情況警告
手動拋出異常
手動拋出異常的方法:raise 空|異常對象
注意:
單raise時,會將當前捕獲的異常直接再次拋出
raise exception_obj;
拋出異常: 不是出錯產生,而是人爲地拋出
1.任何從BaseException派生的類都可以用raise語句拋出,拋出異常用來表明程序遇到的錯誤無法正常執行而需要異常處理
raise BaseException(“some infomation”);
2.異常拋出點後的代碼在拋出異常後不再執行
也可以說異常的拋出終止了代碼段的執行
自定義異常
異常是一個類,用戶定義的異常一般繼承自Exception:
‘’‘自定義的異常類’’’
來個例題:
# 在定義銀行類時,若取錢數大於餘額則作爲異常處理
# (InsufficientFundsException).
# 思路:產生異常的條件是餘額少於取額, 因此是否拋出異常
# 要判斷條件
# 取錢是Withdrawal 方法中定義的動作,因此在該方法中產生
# 異常.
# 處理異常安排在調用Withdrawal 的時候,因此Withdrawal
# 方法要聲明異常,由上級方法調用
# 要定義好自己的異常類
# 要求:捕捉到的異常對象內有餘額和取額的信息
class GetmoneyError(Exception):
def __init__(self, acc, get_money) -> None:
super().__init__()
self.acc = acc
self.get_money = get_money
def __str__(self) -> str:
return f"異常發生的賬戶是{self.acc.acc_id}," \
f"情況爲取款金額{self.get_money},超出賬戶餘額{self.acc.money}"
class Account:
def __init__(self, acc_id, money) -> None:
super().__init__()
self.acc_id = acc_id
self.money = money
def withdraw(self, get_money):
if 0 < get_money < self.money:
return get_money
else:
# print("餘額不足")
# pass
raise GetmoneyError(self, get_money)
if __name__ == '__main__':
try:
acc = Account("001", 123)
acc.withdraw(244)
except GetmoneyError as e:
print(e)