python錯誤處理之try...except...finally...錯誤處理機制。


今天學習了python的錯誤處理。

在程序處理的過程中,經常會出現錯誤,一旦出錯就會非常麻煩。所以有的高級語言通常都內置了一套  try...exept...finaly...的錯誤處理機制,python也不例外。

下面有個try的例子:

try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivisionError as e: print('except:', e) finally: print('finally...') print('END')
因為10/0是錯的,這時候try這一部分會執行錯誤,然后后續代碼不會執行,會直接跳轉至錯誤處理代碼,即except語句塊,執行完后如果有finally語句塊就運行finally, 至此結束。

上面的這一段程序的運行結果為:
try... except: division by zero finally... END
由此可以看出r = 10/0后面的print('result:',r)沒有運行,反而except捕捉到了錯誤所以輸出
division by zero
最后,finally被執行。


如果把上面的程序的“r = 10/0'”改為“r = 10/5”
則會輸出:
try... result: 2 finally... END
可以看出except沒有被執行,但是finally是被執行了。



如果一段程序有多種語句上的錯誤,我們可以用不同的except語句處理。我們可以用多個except捕獲程序里的多種錯誤。
例:
try: print('try...') r = 10 / int('a') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) finally: print('finally...') print('END')
int()函數可能會執行ValueError,所以第一個except會捕獲這個錯值,另一個except捕獲zerodivisionerror,此外如果沒有錯誤我們可以在后面
加一個else,沒有錯誤會執行這個else語句。
 例:
try: print('try...') r = 10 / int('2') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) else: print('no error!') finally:  print('finally...') print('END')


python的錯誤也是class,所有的錯誤類型都繼承自BaseException,各個類型的錯誤之間可能會存在繼承關系,比如UnicodeError是ValueError的子類,
如果catch語句中同時出現了這兩個錯誤,且UnicodeError在ValueError的后面處理的,那么永遠都捕獲不到UnicodeError。


python中內置的常用錯誤類型繼承關系:


使用try…excetp捕獲錯誤一個好處是,可以跨層調用,比如main()調用foo(),foo()調用bar(),而錯誤是在bar中出現的,最后我們只需要在main()中捕獲就行。


def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): try: bar('0') except Exception as e: print('Error:', e) finally: print('finally...')

也就是說,不需要在每個出錯的地方捕獲錯誤,只要在合適的的層次去捕獲錯誤就行了。這樣一來,就大大減少了寫try...except...finally...的麻煩。

調用棧

如果錯誤沒有被捕獲,他就一直往上拋,最好被python解釋器捕獲,打印一個錯誤信息,然后程序退出。來看看err.py:

# err.py: def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): bar('0') main()
執行結果如下:
$ python3 err.py Traceback (most recent call last): File "err.py", line 11, in <module> main() File "err.py", line 9, in main bar('0') File "err.py", line 6, in bar return foo(s) * 2 File "err.py", line 3, in foo return 10 / int(s) ZeroDivisionError: division by zero

出錯並不可怕,可怕的不知道哪里出錯了。解讀信息是定位錯誤的關鍵。我們從上往下可以看到整個錯誤的調用函數鏈:
錯誤信息第一行:
Traceback (most recent call last):

告訴我們這是錯誤的跟蹤信息。
第2~3行:
 File "err.py", line 11, in <module> main()
調用main()出錯了,在代碼文件err.py的第11行代碼,但原因是第9行:
 File "err.py", line 9, in main bar('0')
調用bar(0)出錯了,在代碼文件err.py的第9行代碼,但原因是第6行
 File "err.py", line 6, in bar return foo(s) * 2
原因是return foo(s) * 2這個語句出錯了,但這還不是最終原因,繼續往下看:
 File "err.py", line 3, in foo return 10 / int(s)
原因是return 10 /int(s)這個語句出錯了,這是錯誤產生的源頭,因為下面打印了:
ZeroDivisionError: integer division or modulo by zero

根據錯誤類型zerodivisionerror,我們判斷,int(s)本身並沒有出錯,但是int(s)返回0,在計算10/0時出錯,至此,找到錯源頭。
 
        








 
 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM