Python基础概念_10_异常处理
異常處理
11?異常處理
11.1?簡介
程序是在某個條件下實現(xiàn)某個功能的指令集,如果執(zhí)行的環(huán)境發(fā)生了變化那么程序可能會出異常。比如實現(xiàn)一個打開文件的功能,我們在上章里都是直接打開文件,但實際執(zhí)行時文件可能不存在。如果對這個異常我們沒有做處理,那么python會幫我們處理,不過顯然系統(tǒng)給的系統(tǒng)對用戶來說不是很友好,可讀性不高。而且在沒有加異常捕獲時,程序遇到異常就終止了。所以一般我們都要對異常進行捕獲,讓程序更健壯,能適應(yīng)各種異常的情況。
程序異常示例:
f =open("G:\\tmp\\xiaodao1.txt", "r")?
f.read()?
print("繼續(xù)執(zhí)行呢!")
執(zhí)行結(jié)果:
Traceback (mostrecent call last):
? File "FileOperate.py", line 20, in<module>
??? f = open("D:\\tmp\\xiaodao1.txt","r")
FileNotFoundError:[Errno 2] No such file or directory: 'D:\\tmp\\xiaodao1.txt'
注:此例中如下的代碼在遇到異常時將不會被執(zhí)行:
f.read()?
print ("繼續(xù)執(zhí)行呢!")
11.2?處理異常
處理異常又成異常捕獲,一般我們是通過try/except語句。該語句是用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常信息并處理。這樣當我們的程序出現(xiàn)異常并捕獲到后程序還是會繼續(xù)執(zhí)行。所以上節(jié)的代碼我們修改如下:
try:
??? f = open("G:\\tmp\\xiaodao1.txt","r")?
??? f.read()?
exceptIOError:
??? print ("Error: 沒有找到文件或讀取文件失敗")
???
print("盡管有異常,捕獲后會繼續(xù)執(zhí)行呢!")?
?
執(zhí)行結(jié)果:
Error: 沒有找到文件或讀取文件失敗
盡管異常,捕獲后會繼續(xù)執(zhí)行呢!
如上是個捕獲異常的簡單例子,接下來我們結(jié)合try/except的語法來詳細介紹下異常捕獲的常用處理處理方法。
11.2.1?tryexcept else語句
語法見下:
try:
? ??Normal execution block(代碼塊)
except A:
? ? ?Exception A handle(異常A的具體處理方法)
except B:
? ??Exception B handle(異常B的具體處理方法)
except:
? ??Other exception handle(其它異常的具體處理方法)
else:
? ? ?if no exception,get here(如果沒有異常則處理)
finally:
????final execution block (不論是否異常都會被執(zhí)行到)?
執(zhí)行順序說明:
正常時程序會執(zhí)行try里面的Normal execution block,當出現(xiàn)異常時,則會中斷當前Normalexecution block中的執(zhí)行跳轉(zhuǎn)到對應(yīng)的異常處理塊里執(zhí)行異常處理的代碼。python從第一個except X處開始查找,如果找到了對應(yīng)的exception類型則進入該異常里的處理。如果沒有找到則直接進入except塊處進行處理。
注:
1)? 上面語法里的except塊是個可選項,如果代碼里沒有出現(xiàn),該異常將會被提交給python進行默認處理,處理方式則是終止應(yīng)用程序并打印提示信息。
2)? 異常里的代碼執(zhí)行順序是 try-->exceptX-->except-->else-->finally。其中except是except X沒找到時執(zhí)行,else是沒有異常時執(zhí)行,finally是無論有沒有異常都會執(zhí)行。
代碼示例:
?
如下是個鍵盤接受用戶輸入的程序
try:
??? text = input('請輸入些單詞')
exceptEOFError:
??? print('你為什么輸入個EOF(windows里按ctrl+z,linux里是ctrl+c)給我?')
exceptKeyboardInterrupt:
??? print('你輸出了取消鍵ctr+c')
else:
??? print('你輸入了 {0}'.format(text))
finally:
??? print('無論是否異常最終都會被執(zhí)行finally!')
執(zhí)行結(jié)果:
1)??????場景一輸入ctrl+z模擬程序終止
請輸入些單詞:^Z
你為什么輸入個EOF(windows里按ctrl+z,linux里是ctrl+c)給我?
無論是否異常最終都會被執(zhí)行finally!
2)??????場景二輸入ctrl+c模擬終止輸入
請輸入些單詞:
你輸出了取消鍵ctr+c
無論是否異常最終都會被執(zhí)行finally!
3)??????場景三正常輸入hello xiaodao
請輸入些單詞:hello xiaodao
你輸入了 hello xiaodao
無論是否異常最終都會被執(zhí)行finally!
11.2.2?tryexcept語句
該異常捕獲語句是上述完整語句的簡化版。
代碼示例:
?
如下是個鍵盤接受用戶輸入的程序
try:
??? text = input('請輸入些單詞:')
except:
??? print('你的輸入有誤')
else:
??? print('你輸入了 {0}'.format(text))
finally:
??? print('無論是否異常最終都會被執(zhí)行finally!')???
執(zhí)行結(jié)果:
1)??????場景一輸入ctrl+z模擬程序終止
請輸入些單詞:^Z
你的輸入有誤
無論是否異常最終都會被執(zhí)行finally!
2)??????場景二輸入ctrl+c模擬終止輸入
請輸入些單詞:
你的輸入有誤
無論是否異常最終都會被執(zhí)行finally!
3)??????場景三輸入hello world
請輸入些單詞:hello world
你輸入了 hello world
無論是否異常最終都會被執(zhí)行finally!
如果你想查看異常的詳細原因,還可以將異常記錄到一個文件里。修改后的代碼見下:
改善后代碼:
importtraceback
try:
??? text = input('請輸入些單詞:')
except:
??? print('你的輸入有誤,詳細錯誤信息,請查看c:\\inputerror.txt')
??? f=open("c:\\inputerror.txt",'a')?
??? traceback.print_exc(file=f)?
??? f.flush()?
??? f.close()
else:
??? print('你輸入了 {0}'.format(text))
finally:
??? print('無論是否異常最終都會被執(zhí)行finally!')
?
執(zhí)行結(jié)果:
請輸入些單詞:^Z
你的輸入有誤,詳細錯誤信息,請查看c:\inputerror.txt
無論是否異常最終都會被執(zhí)行finally!
通過查看c:\inputerror.txt里的內(nèi)容,我們知道這里是個EOFError。
Traceback (mostrecent call last):
? File "FileOperate.py", line 115, in<module>
??? text = input('請輸入些單詞:')
EOFError
11.2.3?tryfinally語句
該語句沒有對異常進行處理,即無論是否有異常都會正常執(zhí)行但異常會被python捕獲到并終止程序。
try:
??? text = input('請輸入些單詞:')
finally:
??? print('無論是否異常最終都會被執(zhí)行finally!')
print("程序異常后將不會執(zhí)行,反之會顯示")
?
執(zhí)行結(jié)果:
?
1)??????場景一輸入ctrl+z模擬程序終止
請輸入些單詞:^Z
無論是否異常最終都會被執(zhí)行finally!
Traceback (mostrecent call last):
? File "FileOperate.py", line 129, in<module>
??? text = input('請輸入些單詞:')
EOFError
?
注:這里出現(xiàn)異常,最后一行的print函數(shù)沒有再執(zhí)行。
?
2)??????場景一輸入hello world
請輸入些單詞:hellow world
無論是否異常最終都會被執(zhí)行finally!
程序異常后將不會執(zhí)行,反之會顯示
注:不建議這樣使用try except和try finally方式捕獲異常,因為更細分的異常沒有個個捕獲。
11.3?拋出異常
如果我們知道程序中會有一個很顯著的異常時可以使用 raise 語句拋出它。比方0不能做分母。
代碼示例:
defdivide(x, y):
??? if y == 0 :?
??????? raise ZeroDivisionError('The zero is notallow')?
??? return x / y
a=input("請輸入個數(shù)字:")
b=input("請輸入另外個數(shù)字:")
print("除法結(jié)果:\t"+str(divide(int(a),int(b))))
執(zhí)行結(jié)果:
1)??????場景一輸入0作為分母
請輸入個數(shù)字:10
請輸入另外個數(shù)字:0
Traceback (most recent call last):
? File"FileOperate.py", line 159, in <module>
??? print("除法結(jié)果:\t"+str(divide(int(a),int(b))))
? File"FileOperate.py", line 155, in divide
??? raiseZeroDivisionError('The zero is not allow')
ZeroDivisionError:The zero is not allow
2)??????場景二輸入正常的數(shù)字
請輸入個數(shù)字:10
請輸入另外個數(shù)字:20
除法結(jié)果:?????? 0.5
11.4?自定義異常
自定義異常是通過創(chuàng)建一個新的exception類來擁有自己的異常。異常通過需要繼承自 Exception 類。
代碼示例:
這里定義了一個自己的異常,會記錄外部傳來的value值。主程序里當輸入數(shù)字小于10時觸發(fā)自定義異常。
classMyError(Exception):
??????? def __init__(self, value):
??????????? self.value = value
????? ??def __str__(self):
??????????? return repr(self.value)
???????
a=input("pleaseinput a num:")
ifint(a)<10:
??? try:
??????? raise MyError(a)
??? except MyError as e:
??????? ?print('我自定義的異常觸發(fā)了,輸入的value小于10,它的值是:', e.value)
else:
??? print("查詢正常執(zhí)行!")
執(zhí)行結(jié)果:
1)??????場景一輸入5
please input a num:5
我自定義的異常觸發(fā)了,輸入的value小于10,它的值是: 5
2)??????場景二輸入15
please input a num:18
查詢正常執(zhí)行!
11.5?系統(tǒng)定義異常
Python預(yù)定義了些常用的異常,一般我們叫它系統(tǒng)定義異常。這些異常的詳細信息見下表的說明:
| 異常名稱 | 描述 |
| BaseException | 所有異常的基類 |
| SystemExit | 解釋器請求退出 |
| KeyboardInterrupt | 用戶中斷執(zhí)行(通常是輸入^C) |
| Exception | 常規(guī)錯誤的基類 |
| StopIteration | 迭代器沒有更多的值 |
| GeneratorExit | 生成器(generator)發(fā)生異常來通知退出 |
| StandardError | 所有的內(nèi)建標準異常的基類 |
| ArithmeticError | 所有數(shù)值計算錯誤的基類 |
| FloatingPointError | 浮點計算錯誤 |
| OverflowError | 數(shù)值運算超出最大限制 |
| ZeroDivisionError | 除(或取模)零 (所有數(shù)據(jù)類型) |
| AssertionError | 斷言語句失敗 |
| AttributeError | 對象沒有這個屬性 |
| EOFError | 沒有內(nèi)建輸入,到達EOF 標記 |
| 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)的方法 |
| SyntaxError | 語法錯誤 |
| IndentationError | 縮進錯誤 |
| TabError | Tab 和空格混用 |
| SystemError | 一般的解釋器系統(tǒng)錯誤 |
| TypeError | 對類型無效的操作 |
| ValueError | 傳入無效的參數(shù) |
| UnicodeError | Unicode 相關(guān)的錯誤 |
| UnicodeDecodeError | Unicode 解碼時的錯誤 |
| UnicodeEncodeError | Unicode 編碼時錯誤 |
| UnicodeTranslateError | Unicode 轉(zhuǎn)換時錯誤 |
| Warning | 警告的基類 |
| DeprecationWarning | 關(guān)于被棄用的特征的警告 |
| FutureWarning | 關(guān)于構(gòu)造將來語義會有改變的警告 |
| OverflowWarning | 舊的關(guān)于自動提升為長整型(long)的警告 |
| PendingDeprecationWarning | 關(guān)于特性將會被廢棄的警告 |
| RuntimeWarning | 可疑的運行時行為(runtime behavior)的警告 |
| SyntaxWarning | 可疑的語法的警告 |
| UserWarning | 用戶代碼生成的警告 |
11.6?總結(jié)
這一章我們已經(jīng)討論了try..except和try..finally 語句的用法,同時也學習了如何創(chuàng)建我們自己的異常類型以及如何引發(fā)異常。接下來,我們將探索Python 標準庫。
總結(jié)
以上是生活随笔為你收集整理的Python基础概念_10_异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科创板对标是什么意思
- 下一篇: Python基础概念_11_标准库