python判断正确错误_第16天:Python 错误和异常
by 閑歡
作為 Python 初學(xué)者,在剛學(xué)習(xí) Python 編程時,經(jīng)常會看到一些報錯信息,這些報錯信息就是我們接下來要講的錯誤和異常。
我們在執(zhí)行程序語句的時候,經(jīng)常會看到命令行輸出報錯信息,例如:
>>> while True print('Hello world')
File "", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
這種報錯信息會阻止程序正常運(yùn)行,也就是我們要介紹的錯誤和異常。
錯誤
我們說的錯誤指的是Python的語法錯誤,例如:
>>> if 1=1: print('always')
File "", line 1
if 1=1: print('always')
^
SyntaxError: invalid syntax
上面例子中,在判斷相等的時候應(yīng)該用''==',而不是用'=',執(zhí)行的時候,語法解析器檢查到有錯誤,程序語句終止執(zhí)行,并將錯誤的地方用上箭頭指出來。
語法錯誤很好解決,根據(jù)命令行提示的錯誤位置,檢查語法,改正即可。
異常
在Python中,即使你的代碼沒有語法錯誤,也不能保證程序按照你的想法運(yùn)行完畢,因為在程序執(zhí)行過程中也會有錯誤。
程序運(yùn)行期間檢測到的錯誤被稱為異常,例如:
>>> '1' + 2
Traceback (most recent call last):
File "", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly
大多數(shù)的異常都不會被程序處理,都以錯誤信息的形式顯示出來,如上例所示,提示信息告訴我們int類型不能和str類型相加。
錯誤提示信息會告訴我們異常發(fā)生的上下文,并以調(diào)用棧的形式顯示具體信息,提示信息的最后一行開頭會顯示錯誤類型名稱,上例中,錯誤類型為'TypeError',表示類型異常。
什么是異常
異常是一個事件,該事件會在程序執(zhí)行過程中發(fā)生,從而影響程序的正常執(zhí)行。當(dāng) Python遇到無法處理的程序時,就會引發(fā)一個異常。在 Python 中,異常是一個對象,用于表示一個錯誤,當(dāng) Python腳本發(fā)生異常時我們需要捕獲和處理它,否則程序會終止執(zhí)行。
處理異常
Python 提供了 try/except語句用來捕獲和處理異常。try 語句用來檢測語句塊中是否有錯誤,except 語句則用來捕獲 try 語句中的異常,并進(jìn)行處理,附加的 else 可以在 try 語句沒有異常時執(zhí)行。
語法
下面以最簡單的 try...except...else 為例:
try:
statement(s) # 要檢測的語句塊
except exception:
deal_exception_code # 如果在 try 部份引發(fā)了 'exception' 異常
except exception2, e:
deal_exception2_code # 如果引發(fā)了 'exception2' 異常
else:
no_exception_happend_code #如果沒有異常發(fā)生
try 語句的執(zhí)行邏輯如下:
首先,執(zhí)行 try 子句 (try 和 except 關(guān)鍵字之間的(多行)語句)。
如果沒有異常發(fā)生,則跳過 except 子句 并完成 try 語句的執(zhí)行。
如果在執(zhí)行try 子句時發(fā)生了異常,則跳過該子句中剩下的部分。然后,如果異常的類型和 except 關(guān)鍵字后面的異常匹配,則執(zhí)行 except 子句,然后繼續(xù)執(zhí)行 try 語句之后的代碼。
如果發(fā)生的異常和 except 子句中指定的異常不匹配,則將其傳遞到外部的 try 語句中;如果沒有找到處理程序,則它是一個 未處理異常,執(zhí)行將停止并顯示錯誤消息。
如果 try 語句執(zhí)行時沒有發(fā)生異常,那么將執(zhí)行 else 語句后的語句(如果有 else 的話),然后控制流通過整個 try 語句。
基類
如果發(fā)生的異常和 except 子句中的類是同一個類或者是它的基類,則異常和 except 子句中的類是兼容的(但反過來則不成立 --- 列出派生類的 except 子句與基類兼容)。
實(shí)例
class BException(Exception): #繼承Exception基類
pass
class CException(BException): #繼承BException基類
pass
class DException(CException): #繼承CException基類
pass
for cls in [BException, CException, DException]:
try:
raise cls() #拋出異常
except DException:
print("D")
except CException:
print("C")
except BException:
print("B")
#輸出
B
C
D
請注意如果 except 子句被顛倒(把 except BException 放到第一個),它將打印 B,B,B --- 因為DException類繼承CException類,CException類繼承BException類,將 except BException 放到第一個可以匹配這三個異常,后面的 except 就不會執(zhí)行。
不帶異常類型的 except
Python可以在所有 except 的最后加上 except 子句,這個子句可以省略異常名,以用作通配符。它可以捕獲前面任何 except (如果有的話)沒有捕獲的所有異常。
try:
statement(s) # 要檢測的語句塊
except exception:
deal_exception_code # 如果在 try 部份引發(fā)了 'exception' 異常
except :
deal_all_other_exception2_code # 處理全部其它異常
else:
no_exception_happend_code #如果沒有異常發(fā)生
實(shí)例
try:
raise BException() #拋出異常
except DException:
print("D")
except:
print("處理全部其它異常") #處理全部其它異常
#輸出
處理全部其它異常
except 語句捕獲多種異常類型
一個 try 語句可能有多個 except 子句,以指定不同異常的處理程序,最多會執(zhí)行一個處理程序。 處理程序只處理相應(yīng)的 try 子句中發(fā)生的異常,而不處理同一 try 語句內(nèi)其他處理程序中的異常。一個 except 子句可以將多個異常命名為帶括號的元組。
try:
statement(s) # 要檢測的語句塊
except exception:
deal_exception_code # 如果在 try 部份引發(fā)了 'exception' 異常
except (Exception1[, Exception2[,...ExceptionN]]]) :
deal_all_other_exception2_code # 處理多個異常
else:
no_exception_happend_code #如果沒有異常發(fā)生
實(shí)例
try:
raise BException() #拋出異常
except (BException, DException):
print("D")
except:
print("處理全部其它異常") #處理全部其它異常
else:
print("沒有異常發(fā)生") #沒有異常發(fā)生
#輸出
D
try - finally 語句
finally 語句用于無論是否發(fā)生異常都將執(zhí)行最后的代碼。
try:
# <語句>
finally:
# <語句> #退出try時總會執(zhí)行
實(shí)例
try:
raise BException() #拋出異常
except (BException, DException):
print("D")
except:
print("處理全部其它異常") #處理全部其它異常
else:
print("沒有異常發(fā)生") #沒有異常發(fā)生
finally:
print("你們繞不過我,必須執(zhí)行") #必須執(zhí)行的代碼
#輸出
D
你們繞不過我,必須執(zhí)行
這里注意 finally 和 else 的區(qū)別,finally 是無論是否有異常都會執(zhí)行,而 else 語句只有沒有異常時才會執(zhí)行。也就是說如果沒有異常,那么 finally 和 else 都會執(zhí)行。
異常的參數(shù)
except 子句可以在異常名稱后面指定一個變量。這個變量和一個異常實(shí)例綁定,它的參數(shù)是一個元組,通常包含錯誤字符串,錯誤數(shù)字,錯誤位置,存儲在 .args 中。為了方便起見,異常實(shí)例定義了__str__() ,因此可以直接打印參數(shù)而無需引用 .args。
try:
# 正常的操作 ......
except ExceptionType as inst:
# 可以在這輸出 inst 的值.....
實(shí)例
try:
x = 1 / 0 # 除數(shù)為0
except ZeroDivisionError as err: #為異常指定變量err
print("Exception")
print(err.args) #打印異常的參數(shù)元組
print(err) #打印參數(shù),因為定義了__str__()
#輸出
Exception
('division by zero',)
division by zero
觸發(fā)異常
Python 提供了 raise 語句用于手動引發(fā)一個異常。
語法
raise [Exception [, args [, traceback]]]
參數(shù)說明
Exception:異常的類型,例如 ZeroDivisionError
args:異常參數(shù)值,可選,默認(rèn)值 "None"
traceback:可選,用于設(shè)置是否跟蹤異常對象
異常參數(shù)值可以是一個字符串,類或?qū)ο?/p>
實(shí)例
def diyException(level):
if level > 0:
raise Exception("raise exception", level) #主動拋出一個異常,并且?guī)в袇?shù)
print('我是不會執(zhí)行的') #這行代碼不會執(zhí)行
try:
diyException(2) #執(zhí)行異常方法
except Exception as err: #捕獲異常
print(err) #打印異常參數(shù)
#輸出
('raise exception', 2)
為了能夠捕獲異常,"except"語句必須有用相同的異常來拋出類對象或者字符串。如果要捕獲上面代碼拋出的異常,except 語句應(yīng)該如下所示:
#定義函數(shù)
def diyException(level):
if level > 0:
raise Exception("error level", level) #主動拋出一個異常,并且?guī)в袇?shù)
print('我是不會執(zhí)行的') #這行代碼不會執(zhí)行
try:
diyException(2) #執(zhí)行異常方法
except 'error level' as err: #捕獲異常
print(err) #打印異常參數(shù)
#輸出
Traceback (most recent call last):
File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in
diyException(2) #執(zhí)行異常方法
File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
raise Exception("error level", level) #主動拋出一個異常,并且?guī)в袇?shù)
Exception: ('error level', 2)
當(dāng)然,我們也可以通過 traceback 來捕獲異常:
import traceback
#定義函數(shù)
def diyException(level):
if level > 0:
raise Exception("error level", level) #主動拋出一個異常,并且?guī)в袇?shù)
print('我是不會執(zhí)行的') #這行代碼不會執(zhí)行
try:
diyException(2) #執(zhí)行異常方法
except Exception: #捕獲異常
traceback.print_exc()
#輸出
Traceback (most recent call last):
File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in
diyException(2) #執(zhí)行異常方法
File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
raise Exception("error level", level) #主動拋出一個異常,并且?guī)в袇?shù)
Exception: ('error level', 2)
用戶自定義異常
除了使用 Python 內(nèi)置的異常,我們還可以創(chuàng)建自己的異常類型。創(chuàng)建自己的異常非常簡單,只需要創(chuàng)建一個類,并繼承 Exception 類或其子類。
下面的代碼創(chuàng)建了一個異常 DiyError 繼承自 Python 內(nèi)置的 RuntimeError,用于在異常觸發(fā)時輸出更多的信息。
#自定義異常
class DiyError(RuntimeError):
def __init__(self, arg):
self.args = arg
try:
raise DiyError("my diy exception") #觸發(fā)異常
except DiyError as e:
print(e)
定義好了之后,我們就可以在 except 語句后使用 DiyError 異常,變量 e 是用于創(chuàng)建 DiyError 類的實(shí)例。我們也可以通過 raise 語句手動觸發(fā)這個異常。
預(yù)定義的清理行為
一些對象定義了標(biāo)準(zhǔn)的清理行為,無論系統(tǒng)是否成功的使用了它,一旦不需要它了,那么這個標(biāo)準(zhǔn)的清理行為就會執(zhí)行。
for line in open("myfile.txt"):
print(line, end="")
上面這個例子嘗試打開一個文件,然后把內(nèi)容打印出來。但是有一個問題:當(dāng)執(zhí)行完畢后,程序沒有關(guān)閉文件流,文件會保持打開狀態(tài)。
關(guān)鍵詞 with 語句就可以保證諸如文件之類的對象在使用完之后一定會正確的執(zhí)行他的清理方法。
with open("myfile.txt") as f:
for line in f:
print(line, end="")
以上這段代碼執(zhí)行完畢后,就算在處理過程中出問題了,文件 f 總是會關(guān)閉。這里面的原理就是使用了 finally 機(jī)制,有興趣的可以去深入了解一下。
總結(jié)
本節(jié)給大家介紹了 Python 錯誤和異常的使用,掌握了錯誤和異常的處理,可以極大地提高程序的健壯性,為程序的持續(xù)完整運(yùn)行提供了保障。
關(guān)注公眾號:python技術(shù),回復(fù)"python"一起學(xué)習(xí)交流
總結(jié)
以上是生活随笔為你收集整理的python判断正确错误_第16天:Python 错误和异常的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3 读取文本文件_pytho
- 下一篇: dev layoutview 怎么显示大