https://www.jb51.net/article/85627.htm
https://www.jb51.net/article/60638.htm
http://c.biancheng.net/view/vip_7103.html
(try finally)
https://baijiahao.baidu.com/s?id=1636646977338815546&wfr=spider&for=pc
http://www.360doc.com/content/19/0703/20/54508727_846532231.shtml
https://www.cnblogs.com/windlazio/archive/2013/01/24/2874417.html
Python try except異常處理詳解
python標准異常
異常名稱 | 描述 |
---|---|
BaseException | 所有異常的基類 |
SystemExit | 解釋器請求退出 |
KeyboardInterrupt | 用戶中斷執行(通常是輸入^C) |
Exception | 常規錯誤的基類 |
StopIteration | 迭代器沒有更多的值 |
GeneratorExit | 生成器(generator)發生異常來通知退出 |
SystemExit | Python 解釋器請求退出 |
StandardError | 所有的內建標准異常的基類 |
ArithmeticError | 所有數值計算錯誤的基類 |
FloatingPointError | 浮點計算錯誤 |
OverflowError | 數值運算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有數據類型) |
AssertionError | 斷言語句失敗 |
AttributeError | 對象沒有這個屬性 |
EOFError | 沒有內建輸入,到達EOF 標記 |
EnvironmentError | 操作系統錯誤的基類 |
IOError | 輸入/輸出操作失敗 |
OSError | 操作系統錯誤 |
WindowsError | 系統調用失敗 |
ImportError | 導入模塊/對象失敗 |
KeyboardInterrupt | 用戶中斷執行(通常是輸入^C) |
LookupError | 無效數據查詢的基類 |
IndexError | 序列中沒有沒有此索引(index) |
KeyError | 映射中沒有這個鍵 |
MemoryError | 內存溢出錯誤(對於Python 解釋器不是致命的) |
NameError | 未聲明/初始化對象 (沒有屬性) |
UnboundLocalError | 訪問未初始化的本地變量 |
ReferenceError | 弱引用(Weak reference)試圖訪問已經垃圾回收了的對象 |
RuntimeError | 一般的運行時錯誤 |
NotImplementedError | 尚未實現的方法 |
SyntaxError | Python 語法錯誤 |
IndentationError | 縮進錯誤 |
TabError | Tab 和空格混用 |
SystemError | 一般的解釋器系統錯誤 |
TypeError | 對類型無效的操作 |
ValueError | 傳入無效的參數 |
UnicodeError | Unicode 相關的錯誤 |
UnicodeDecodeError | Unicode 解碼時的錯誤 |
UnicodeEncodeError | Unicode 編碼時錯誤 |
UnicodeTranslateError | Unicode 轉換時錯誤 |
Warning | 警告的基類 |
DeprecationWarning | 關於被棄用的特征的警告 |
FutureWarning | 關於構造將來語義會有改變的警告 |
OverflowWarning | 舊的關於自動提升為長整型(long)的警告 |
PendingDeprecationWarning | 關於特性將會被廢棄的警告 |
RuntimeWarning | 可疑的運行時行為(runtime behavior)的警告 |
SyntaxWarning | 可疑的語法的警告 |
UserWarning | 用戶代碼生成的警告 |
什么是異常?
異常即是一個事件,該事件會在程序執行過程中發生,影響了程序的正常執行。
一般情況下,在Python無法正常處理程序時就會發生一個異常。
異常是Python對象,表示一個錯誤。
當Python腳本發生異常時我們需要捕獲處理它,否則程序會終止執行
什么是異常處理?
捕捉異常可以使用try/except語句。
try/except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常信息並處理。
如果你不想在異常發生時結束你的程序,只需在try里捕獲它。
當執行可能出錯的代碼時,需要適當的異常處理程序用於阻止潛在的錯誤發生。在異常可能發生的地方添加異常處理程序,對於用戶明確錯誤時一種好方法。即使不能例可解決問題,但是可以記錄運行環境並且停止程序運行。在你不能提供自己的異常捕獲代碼時,python會輸出錯誤消息和關於錯誤發生處的消息,再停止程序
>>> short_list=[1,2,3] >>> position=5 >>> short_list[position] Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> short_list[position] IndexError: list index out of range >>>
Python 中,用try except else
語句塊捕獲並處理異常,其基本語法結構如下所示:
try: 可能產生異常的代碼塊 except [ (Error1, Error2, ... ) [as e] ]: 處理異常的代碼塊1 except [ (Error3, Error4, ... ) [as e] ]: 處理異常的代碼塊2 except [Exception]: 處理其它異常 else: 未發生異常
該格式中,[] 括起來的部分可以使用,也可以省略。其中各部分的含義如下:
- (Error1, Error2,...) 、(Error3, Error4,...):其中,Error1、Error2、Error3 和 Error4 都是具體的異常類型。顯然,一個 except 塊可以同時處理多種異常。
- [as e]:作為可選參數,表示給異常類型起一個別名 e,這樣做的好處是方便在 except 塊中調用異常類型(后續會用到)。
- [Exception]:作為可選參數,可以代指程序可能發生的所有異常情況,其通常用在最后一個 except 塊。
從try except else
的基本語法格式可以看出,try 塊有且僅有一個,但 except 代碼塊可以有多個,且每個 except 塊都可以同時處理多種異常。
當程序發生不同的意外情況時,會對應特定的異常類型,Python 解釋器會根據該異常類型選擇對應的 except 塊來處理該異常。
try except else 語句的執行流程如下:
- 首先執行 try 中的代碼塊,如果執行過程中出現異常,系統會自動生成一個異常類型,並將該異常提交給 Python 解釋器,此過程稱為捕獲異常。
- 當 Python 解釋器收到異常對象時,會尋找能處理該異常對象的 except 塊,如果找到合適的 except 塊,則把該異常對象交給該 except 塊處理,這個過程被稱為處理異常。如果在try后的語句里發生了異常,卻沒有匹配的except子句,異常將被遞交到上層的try,或者到程序的最上層(這樣將結束程序,並打印缺省的出錯信息)
- 如果在try子句執行時沒有發生異常,python將執行else語句后的語句(如果有else的話),然后控制流通過整個try語句
事實上,不管程序代碼塊是否處於 try 塊中,甚至包括 except 塊中的代碼,只要執行該代碼塊時出現了異常,系統都會自動生成對應類型的異常。但是,如果此段程序沒有用 try 包裹,又或者沒有為該異常配置處理它的 except 塊,則 Python 解釋器將無法處理,程序就會停止運行;反之,如果程序發生的異常經 try 捕獲並由 except 處理完成,則程序可以繼續執行。
示例(1):代碼運行正常
try: a = int(input("輸入被除數:")) b = int(input("輸入除數:")) c = a / b print("您輸入的兩個數相除的結果是:", c ) except (ValueError, ArithmeticError): print("程序發生了數字格式異常、算術異常之一") except : print("未知異常") else: print("未發生異常") print("程序繼續運行")
運行結果:
輸入被除數:9 輸入除數:3 您輸入的兩個數相除的結果是: 3.0 未發生異常 程序繼續運行
示例(2)代碼運行失敗
輸入被除數:a
程序發生了數字格式異常、算術異常之一
程序繼續運行
>>>
上面程序中,第 6 行代碼使用了(ValueError, ArithmeticError)來指定所捕獲的異常類型,這就表明該 except 塊可以同時捕獲這 2 種類型的異常;第 8 行代碼只有 except 關鍵字,並未指定具體要捕獲的異常類型,這種省略異常類的 except 語句也是合法的,它表示可捕獲所有類型的異常,一般會作為異常捕獲的最后一個 except 塊,但這不是一個很好的方式,我們不能通過該程序識別出具體的異常信息
除此之外,由於 try 塊中引發了異常,並被 except 塊成功捕獲,因此程序才可以繼續執行,才有了“程序繼續運行”的輸出結果。
獲取特定異常的有關信息
通過前面的學習,我們已經可以捕獲程序中可能發生的異常,並對其進行處理。但是,由於一個 except 可以同時處理多個異常,那么我們如何知道當前處理的到底是哪種異常呢?
其實,每種異常類型都提供了如下幾個屬性和方法,通過調用它們,就可以獲取當前處理異常類型的相關信息:
1)args:返回異常的錯誤編號和描述字符串;
2)str(e):返回異常信息,但不包括異常信息的類型;
3)repr(e):返回較全的異常信息,包括異常信息的類型
try: 1/0 except Exception as e: # 訪問異常的錯誤編號和詳細信息 print(e.args) print(str(e)) print(repr(e))
輸出結果為:
('division by zero',) division by zero ZeroDivisionError('division by zero',)
除此之外,如果想要更加詳細的異常信息,可以使用 traceback 模塊。有興趣的讀者,可自行查閱資料學習
從程序中可以看到,由於 except 可能接收多種異常,因此為了操作方便,可以直接給每一個進入到此 except 塊的異常,起一個統一的別名 e。
python中的try/except/else/finally語句
與其他語言相同,在python中,try/except語句主要是用於處理程序正常執行過程中出現的一些異常情況,如語法錯誤(python作為腳本語言沒有編譯的環節,在執行過程中對語法進行檢測,出錯后發出異常消息)、數據除零錯誤、從未定義的變量上取值等;
Python 異常處理機制還提供了一個 finally 語句,通常用來為 try 塊中的程序做掃尾清理工作。如在通信過程中,無論通信是否發生錯誤,都需要在通信完成或者發生錯誤時關閉網絡連接。
注意,和 else 語句不同,finally 只要求和 try 搭配使用,而至於該結構中是否包含 except 以及 else,對於 finally 不是必須的(else 必須和 try except 搭配使用)。
在整個異常處理機制中,finally 語句的功能是:無論 try 塊是否發生異常,最終都要進入 finally 語句,並執行其中的代碼塊。
基於 finally 語句的這種特性,在某些情況下,當 try 塊中的程序打開了一些物理資源(文件、數據庫連接等)時,由於這些資源必須手動回收,而回收工作通常就放在 finally 塊中。
Python 垃圾回收機制,只能幫我們回收變量、類對象占用的內存,而無法自動完成類似關閉文件、數據庫連接等這些的工作。
讀者可能會問,回收這些物理資源,必須使用 finally 塊嗎?當然不是,但使用 finally 塊是比較好的選擇。首先,try 塊不適合做資源回收工作,因為一旦 try 塊中的某行代碼發生異常,則其后續的代碼將不會得到執行;其次 except 和 else 也不適合,它們都可能不會得到執行。而 finally 塊中的代碼,無論 try 塊是否發生異常,該塊中的代碼都會被執行。
try: Normal execution block except A: Exception A handle except B: Exception B handle except: Other exception handle else: if no exception,get here finally: print("finally")
class AError(Exception): """AError---exception""" print('AError') try: #raise AError asdas('123') except AError: print("Get AError") except: print("exception") else: print("else") finally: print("finally") print("hello wolrd")
try: a = int(input("請輸入 a 的值:")) print(20/a) except: print("發生異常!") else: print("執行 else 塊中的代碼") finally : print("執行 finally 塊中的代碼")
運行此程序:
請輸入 a 的值:4 5.0 執行 else 塊中的代碼 執行 finally 塊中的代碼
可以看到,當 try 塊中代碼為發生異常時,except 塊不會執行,else 塊和 finally 塊中的代碼會被執行。
再次運行程序:
請輸入 a 的值:a 發生異常! 執行 finally 塊中的代碼
可以看到,當 try 塊中代碼發生異常時,except 塊得到執行,而 else 塊中的代碼將不執行,finally 塊中的代碼仍然會被執行。
finally 塊的強大還遠不止此,即便當 try 塊發生異常,且沒有合適和 except 處理異常時,finally 塊中的代碼也會得到執行。例
try: #發生異常 print(20/0) finally : print("執行 finally 塊中的代碼")
程序執行結果為:
執行 finally 塊中的代碼 Traceback (most recent call last): File "D:\python3.6\1.py", line 3, in <module> print(20/0) ZeroDivisionError: division by zero
可以看到,當 try 塊中代碼發生異常,導致程序崩潰時,在崩潰前 Python 解釋器也會執行 finally 塊中的代碼。
Python中關於try...finally的一些疑問
以“Open-Read-Write"文件為例,執行操作中,當某流程執行失敗時,都要先Close文件后再返回相關內容。如果操作流程多,每個步驟都要寫上close函數,這樣會出現漏寫的情況
以try-except-else-finally。的好處是避免了頻繁寫close函數、
先以代碼引入
def func(x): try: return ++x finally: return x+1
func(11)
你覺得是幾?
看到問題,覺得肯定是12啊
下邊看看我寫的例子,就明白其中的問題了。
示例1
def f(): try: print(1) return 1 finally: print(0) return 0
f()
結果為 1 0 0
以運行結果為准,說明無論try里執行什么,即使是return,也會調用finally的。
但是有一個問題,為什么最后輸出的不是1而是0呢?明明try里面已經返回1了!
def f(): try: print(1) return 1 finally: print(0) #return 0
將finally的return屏蔽掉,你或許猜到結果了
結果為 1 0 1
詫異嗎?
對比上個結果,說明try的返回值被finally的返回值覆蓋了,或許是因為一個函數只能有一個返回值,以最后一個結果為准
由此我想再驗證下else的情況,如下:
def f(): try: print(1) return 1 except: return 2 else: print(3) return 3 finally: print(0) #return 0
你覺得,沒有異常else會執行嗎?
如你所料,並沒有執行。
結果為 1 0 1
說明try里面運行完之后return,阻擋了else的執行,但是並沒有影響finally的執行。
“如果try中沒有異常,那么except部分將跳過,執行else中的語句。
finally是無論是否有異常,最后都要做的一些事情。”
這里補充一句,在含有return的情況下,並不會阻礙finally的執行。