異常處理涉及的關鍵字: try: 理解它是掃描器,將可能出現異常的代碼放入其中; 如果在執行的過程中出現異常對象了,掃描器會立即察覺到此異常對象, 但是它沒有處理它的能力,所以會將異常對象給到except(捕獲器)進行處理 except: 理解它是捕獲器,後面可以定義異常類型,並且和as關鍵字配合使 ...
Python 有兩種錯誤很容易辨認:語法錯誤和異常(本文將重點介紹python的異常)。
python語法錯誤:
Python 的語法錯誤或者稱之為解析錯,是初學者經常碰到的;
>>>while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax
函數 print() 被檢查到有錯誤,是它前面缺少了一個冒號 : 。語法分析器指出了出錯的一行,並且在最先找到的錯誤的位置標記了一個小小的箭頭。
python異常:
即便 Python 程式的語法是正確的,在運行它的時候,也有可能發生錯誤。運行期檢測到的錯誤被稱為異常。異常即是一個事件,該事件會在程式執行過程中發生,影響了程式的正常執行;一般情況下,在Python無法正常處理程式時就會發生一個異常;異常是Python對象,表示一個錯誤;當Python腳本發生異常時我們需要捕獲處理它,否則程式會終止執行。
>>>10 * (1/0) # 0 不能作為除數,觸發異常 Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam 未定義,觸發異常 Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'spam' is not defined
>>> '2' + 2 # int 不能與 str 相加,觸發異常 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Can't convert 'int' object to str implicitly
異常以不同的類型出現,這些類型都作為信息的一部分列印出來: 例子中的類型有 ZeroDivisionError,NameError 和 TypeError。錯誤信息的前面部分顯示了異常發生的上下文,並以調用棧的形式顯示具體信息。
python異常的處理:
python提供了兩個非常重要的功能來處理python程式在運行中出現的異常和錯誤。你可以使用該功能來調試python程式。異常處理和斷言(Assertions)。
異常處理涉及的5個關鍵字:
try:理解它是掃描器,將可能出現異常的代碼放入其中;如果在執行的過程中出現異常對象了,掃描器會立即察覺到此異常對象,但是它沒有處理它的能力,所以會將異常對象給到except(捕獲器)進行處理。
except:理解它是捕獲器,後面可以定義異常類型,並且和as關鍵字配合使用;定義多個except是合法的,但是它的執行順序是有由上往下,一旦匹配上某個except,之後的就不執行了;匹配成功就理解將異常對象捕獲住並且kill,順便會執行except內部的代碼。(註意:except不能捕獲處理類似於語法錯誤這種情況)
finally:將一定需要被執行的代碼定義其中,【記住】:finally一定會被執行(核心);使用場景:像關閉文件、斷開資料庫連接等行為都可以放入到finally中。
else:位置在finally前,except後;效果/作用類似於迴圈;沒有異常對象出現,else就會被執行,反之不會被執行。
raise:手動拋出一個異常類型的對象,定義:raise 異常類型(msg)。
定義格式:
格式一: 多個except語句併列存在,每個except包含一種類型,如果它們之間沒有子父類的關係(互斥),那麼誰上誰下無所謂, 如果它們之間存在子父類的關係(包含),那麼小的在上,大的在下。
try: 語句塊1 except 異常類型1 as e: 語句塊2 except 異常類型2 as e: 語句塊3 except 異常類型3 as e: 語句塊4 finally: 語句塊5
格式二:一個except具備多個捕獲能力(捕獲多種不同類型異常對象)。
try: 語句塊1 except 異常類型1 as e: 語句塊2 except 異常類型2 as e: 語句塊3 except 異常類型3 as e: 語句塊4 except (異常類型4,異常類型5,...,異常類型m) as e: finally: 語句塊5
格式三:Exception是所有異常類型的父類型,它都是定義在最後一個except的位置。
try: 語句塊1 except 異常類型1 as e: 語句塊2 except 異常類型2 as e: 語句塊3 except 異常類型3 as e: 語句塊4 except (異常類型4,異常類型5,...,異常類型m) as e: 語句塊5 except Exception as e: 語句塊6 finally: 語句塊7
格式四: 【Exception的簡化版使用】:如果定義了except,那麼它必須是最後一個except,它可以理解為是Exception的簡化形式
try: 語句塊1 except 異常類型1 as e: 語句塊2 except 異常類型2 as e: 語句塊3 except 異常類型3 as e: 語句塊4 except (異常類型4,異常類型5,...,異常類型m) as e: 語句塊5 except: 語句塊6 finally: 語句塊7
代碼演示自動拋出異常對象:
2 3 def div(a,b): 4 print(a / b) 5 6 div(10,0) 7 8 # 演示異常處理的方式一:try ... except ... 9 try: 10 print(10/0) 11 except ZeroDivisionError as e: 12 print(e) 13 14 try: 15 print("abc"+123) 16 except TypeError as e: 17 print(e) 18 19 try: 20 print(a) 21 except NameError as e: 22 print(e) 23 24 try: 25 lt = [1,2,3,4,5] 26 print(lt[5]) 27 except IndexError as e: 28 print(e) 29 30 try: 31 fr = open(r'C:\Users\Administrator\Desktop\kaifanglist1.txt','r',encoding='utf-8') 32 print(fr.read()) 33 fr.close() 34 except FileNotFoundError as e: 35 print(e) 36 37 except(ZeroDivisionError,TypeError,NameError,IndexError,FileNotFoundError) as e: 38 print('我能捕獲5種類型的異常對象...') 39 40 except Exception as e: 41 print('我是所有異常類型的父類型,我能解決所有的異常類型對象...') 42 43 except: 44 print('我是Exception的簡化形式,我只能出現在最後一個except的位置...')
代碼演示finally語句的使用:將一定要被執行的代碼定義在finally中,不管之前的代碼怎麼樣(異常是否被解決),finally一定會被執行,在後期的學習和開發中,我們將關閉文件、關閉資料庫連接等操作都定finally中。
1 try: 2 fr = open(r'C:\Users\Administrator\Desktop\a.txt','r') # 文件能打開 3 print(fr.read()) 4 print(10 / 0) 5 # fr.close() # 因為關閉文件操作是一定要被執行的 但是在try裡面也有可能存在風險性,當print(10 / 0)行不了,則無法執行close操作,所以關閉文件需要放在finally語句當中
6 except: 7 print('解決異常') 8 finally: 9 print('我是finally,我一定會被執行...') 10 fr.close() 11 12 13 # 但是如果一開始就是一個打不開的文件,則也沒有辦法關閉文件 14 fr = 0 15 try: 16 fr = open(r'C:\Users\Administrator\Desktop\a111.txt','r') # 沒有此文件名 (文件存在則fr不為None值) 17 print(fr.read()) 18 except: 19 print('解決異常') 20 finally: 21 print('我是finally,我一定會被執行...') 22 if fr: # fr為None值則if為False,否則為True,執行以下指令(為了安全性) 23 fr.close()
finally案例演示二(進一步理解):
1 # Finally案例:分別輸出了哪些內容,返回值是多少 2 3 def func(): 4 try: 5 print('我是try...') 6 print(10 / 2) 7 return 1 #執行此步 則函數就結束了,又因為finally一定要被執行,所以return 1不會被執行,直接調到finally 8 except: 9 print('我是except...') 10 return 2 11 finally: 12 print('我是finally...') 13 return 3 14 15 num = func() 16 print(num) 17 '''結果得到是 18 我是try... 19 5.0 20 我是finally... 21 3''' 22 23 # 如果題目改為如下,則 24 def func(): 25 try: 26 print('我是try...') 27 print(10 / 0) 28 return 1 29 except: 30 print('我是except...') 31 return 2 #執行此步 則函數就結束了,又因為finally一定要被執行,所以return 2不會被執行,直接調到finally 32 finally: 33 print('我是finally...') 34 return 3 35 36 num = func() 37 print(num) 38 '''結果得到是 39 我是try... 40 我是except... 41 我是finally... 42 3''' 43
【補充】with open...操作:不需要程式員人為的去書寫 close() 函數
1 With open(r'C:\Users\Administrator\Desktop\a.txt','r')as fr: 2 print(fr.read())
解決異常也是一樣:
1 try: 2 with open(r'C:\Users\Administrator\Desktop\a.txt','r') as fr: 3 print(fr.read()) 4 except: 5 print('解決異常...')
代碼演示else語句和異常處理機制配合使用:如果try中沒有出現異常對象,那麼else語句就一定會被執行,如果try中出現了異常對象,就算被處理了,else還是不會被執行。
1 try: 2 print('我是try...') 3 print(10 / 0) 4 except Exception as e: 5 print('我是except...') 6 else: 7 print('我是else...') 8 finally: 9 print('我是finally...')
10 #得到 11 我是try... 12 我是except... 13 我是finally... 14 15 #如果把print(10 / 0) 改為print(10 / 2) 16 17 #得到 18 我是try... 19 5.0 20 我是else... 21 我是finally...
代碼演示raise的使用:(手動拋出異常對象)
1 age = 18 2 if age < 0 or age > 130: 3 try: 4 raise Exception('年齡有問題...') 5 except: 6 print('年齡不合法...正在處理') 7 pass 8 else: 9 print('年齡為:%d' %age) 10 print('能走嗎?') 11 12 #得到結果為 13 年齡為:18 14 能走嗎? 15 16 #如果第一行是age=-18 17 #得到結果為 18 年齡不合法...正在處理 19 能走嗎?
1 # 演示異常處理的方式二:不斷往上級傳遞異常對象,迴避問題的方式 2 3 def m1(): 4 print('我是m1...') 5 print(10 / 0) 6 7 def m2(): 8 print('我是m2...') 9 # try: 10 m1() 11 # except: 12 # pass 13 14 def m3(): 15 print('我是m3...') 16 try: 17 m2() 18 except: 19 pass 20 21 m3() 22 #得到結果 23 我是m3... 24 我是m2... 25 我是m1...
python標準異常總結:
BaseException | 所有異常的基類 |
SystemExit | 解釋器請求退出 |
KeyboardInterrupt | 用戶中斷執行(通常是輸入^C) |
Exception | 常規錯誤的基類 |
StopIteration | 迭代器沒有更多的值 |
GeneratorExit | 生成器(generator)發生異常來通知退出 |
StandardError | 所有的內建標準異常的基類 |
ArithmeticError | 所有數值計算錯誤的基類 |
FloatingPointError | 浮點計算錯誤 |
OverflowError | 數值運算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有數據類型) |
AssertionError | 斷言語句失敗 |
AttributeError | 對象沒有這個屬性 |
EOFError | 沒有內建輸入,到達EOF 標記 |
EnvironmentError | 操作系統錯誤的基類 |
IOError | 輸入/輸出操作失敗 |
OSError | 操作系統錯誤 |
WindowsError | 系統調用失敗 |
ImportError | 導入模塊/對象失敗 |
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 | 用戶代碼生成的警告 |
【註意事項】:
1).try...finally這種格式是合法的,但是它喪失瞭解決異常對象的能力(所以不會使用)
2).else語句必須配合except使用,出現位置一定是在最後一個except的後面
3).常見的運行時異常類型:ZeroDivisionError:分母為0的異常;TypeError:類型有誤的異常; NameError:沒有定義就使用的異常;IndexError:下標越界的異;FileNotFoundError:文件找不到的異常;...
4).with open ... as ...語句可以優化原始的open操作!體現:它不需要手動close()文件對象
總結:學習異常對象簡單歸納為5個關鍵字:try except finally else raise
python的assert(斷言):
Python的assert(斷言)用於判斷一個表達式,在表達式條件為 false 的時候觸發異常。斷言可以在條件不滿足程式運行的情況下直接返回錯誤,而不必等待程式運行後出現崩潰的情況,例如我們的代碼只能在 Linux 系統下運行,可以先判斷當前系統是否符合條件。
語法格式如下:assert expression
等價於:
if not expression:
raise AssertionError
assert 後面也可以緊跟參數: assert expression [, arguments]
等價於:
if not expression:
raise AssertionError(arguments)
代碼演示assert示例:
1 >>> assert True # 條件為 true 正常執行 2 >>> assert False # 條件為 false 觸發異常 3 Traceback (most recent call last): 4 File "<stdin>", line 1, in <module> 5 AssertionError 6 7 >>> assert 1==1 # 條件為 true 正常執行 8 >>> assert 1==2 # 條件為 false 觸發異常 9 Traceback (most recent call last): 10 File "<stdin>", line 1, in <module> 11 AssertionError 12 13 >>> assert 1==2, '1 不等於 2' 14 Traceback (most recent call last): 15 File "<stdin>", line 1, in <module> 16 AssertionError: 1 不等於 2 17 18 19 # 判斷當前系統是否為 Linux,如果不滿足條件則直接觸發異常,不必執行接下來的代碼: 20 import sys 21 assert ('linux' in sys.platform), "該代碼只能在 Linux 下執行" 22 # 接下來要執行的代碼