Python實用教程系列——異常處理

image

前幾篇文章寫的是關于Xlwings的相關知識,介紹了其相關API的使用方法,大家在使用Xlwing對Excel進行操作的時候,就可以使用推文中介紹的方法完成自己的任務。關于其與VBA的結合的使用,等后期遇到比較好項目的時候我再跟大家介紹。

從現在開始,將開啟新的寫作《Python實用教程系列》,主要是針對自己在項目中,對那些平時使用頻率較高的,覺得重要的知識點進行總結和歸納,以更好的幫助大家在寫代碼的時候起到舉一反三的作用,閑話不多說,這個系列的開篇我們就從-異常處理講起!

百度百科中對異常處理的介紹為:異常處理,是編程語言或計算機硬件里的一種機制,用于處理軟件或信息系統中出現的異常狀況(即超出程序正常執行流程的某些特殊條件)。從這個角度來看,異常處理是保證程序正常運行關鍵,因此異常處理是非常重要的!

在Python中,處理異常的基類是:BaseException,各個異常具體如下所示:

image

一、異常分類

基類BaseException中有一個異常類Warning,這個Warning我們應該遇見的次數很多了,比如我們在運行代碼的時候,比如某一個要模塊版本過低的時候會出現這樣的告警。

記下來我們來介紹上述所列的幾個常見異常:

image

1. AttributeError

class Car():    def __init__(self):        self.car_lenth = 3.5        self.car_height = 1.7        self.car_name = 'Benz'new_car = Carprint(new_car.car_width)

上述代碼最后一行代碼試圖訪問不存在的屬性car_width,這將拋出一下的異常:

AttributeError: type object 'Car' has no attribute 'car_width'

2. IndexError

def len_list(number):    print(number[len(number)] + 1)len_list([1,2,3,4,5])

上述代碼試圖訪問超出列表的索引進行取值,這將拋出異常:

IndexError: list index out of range

3. KeyError

def visit_dic(dic_num):    print(dic_num['4'])dic_123 = {'1':'我', '2':'愛', '3':'python學堂'}visit_dic(dic_123['4'])

上述代碼試圖訪問字典dic_123中不存在的鍵值,這將拋出KeyError: '4'異常

4. NameError

def name_err():    print(name)name_err()

上述代碼中,函數name_err()中試圖打印不存在的name對象,將拋出異常:

NameError: name 'name' is not defined

5. OSError

def open_file(filename):    file=open(filename)file = r'C:\Users\TEN\Desktop\'1.txt'open_file(file)

上述代碼試圖打開桌面一個不存在的文件1.txt,這將拋出OSError異常:

FileNotFoundError:[Errno2]No such file or directory:

"C:\Users\TEN\Desktop\'1.txt"

值的一提的是在python3.3版本以后,IOError(有關于輸入輸出的異常)將并到OSError中,看上述Xmind圖可知FileNotFoundError屬于OSError類。

6. SyntaxError

def syn_error():    print('python知識學堂')    print('今天天氣好)syn_error()

上述代碼第二行的print打印測時候,少了一個“’”,將拋出異常:

SyntaxError: EOL while scanning string literal

7. TypeError

def add_number(parameter1, parameter2):    sum = parameter1 + parameter2    return sumtotal = add_number(1, 2, 3)print(total)

上述代碼的函數add_number接受2個參數,第五行代碼傳入了3個參數,這將拋出類型錯誤的異常:

TypeError: add_number() takes 2 positional arguments but 3 were given

綜上,我們看了7種類型的異常。那么很顯然想到的就是,出現的這些異常我們該怎么處理呢?接下來我們就將介紹處理異常的一些方法:

二、Try-except

異常是使用try-except來進行處理的,使用try-except的好處就是可以讓python執行指定的操作,可以人為定義一些面向用戶友好的一些錯誤信息,幫助用戶定位錯誤。在實際的項目中,我們把可能出現異常的代碼塊放在try中,以便排除異常并保證其余代碼正常運行而不退出。

比如我們使用try-except處理一個ZeroDivisionError異常:

try:    print(100/0)except ZeroDivisionError:    print('分母不能為0')

這里出現錯誤的代碼被放在了try中,如果try中的代碼沒有問題,python將跳過except中的代碼;如果try中的代碼出現問題,則會執行except中的代碼。

這里有一個技巧,就是else模塊的使用,比如:

try:    print(100/1)except ZeroDivisionError:    print('分母不能為0')else:    print('python')

上述代碼輸出:100.0,python。使用else的好處就是可以讓代碼繼續執行,即使遇到一些可能的錯誤,作為一種選擇性的繼續執行時非常nice的。

在拋出異常的時候,我們可以使用except error_type as errorname:的形式,那么使用print(errorname)就可以打印異常對象了,十分方便。

try:    print(100/0)except ZeroDivisionError as zeror:    print('分母不能為0')    print(zeror)else:    print('python')

三、多except

在實際的項目中,我們在一段代碼中需要處理的異常不只一個,比如要同時處理ArithmeticErrorValueErrorArithmeticErrorZeroDivisionError的父類,這個時候我們就可以使用多Try-except方法了,該方法就可以進行多重異常的捕獲了哦。

try:    file = open(r'C:\Users\TEN\Desktop\1.txt')  # 桌面不存在文件1.txt    print(100/0)    print(100/2)except ZeroDivisionError as zeror:    print('分母不能為0')except FileNotFoundError as fn:    print(fn)    print('python')else:    print('運行結束')

程序正常運行且上述代碼輸出:

[Errno 2] No such file or directory: "C:\Users\TEN\Desktop\'1.txt"

python

上述代碼使用多個except來進行不同的異常處理,大家可以好好研究一下其中的打印為什么是這樣。

四、嵌套Try-except

在實際的項目中我們可能還會遇到這樣的情況:在一個try-except中處理了一個異常,在這個異常處理之中我們還要進行異常的處理,此時就需要使用嵌套Try-except了,正好python中也是支持這個嵌套的。我們來看一個實際的例子,來感受一下:

def trying_test():    try:        try:            print(100/0)        except:            print('分母不能為0')        try:            file = open(r'C:\Users\TEN\Desktop\1.txt')        except FileNotFoundError as fn:            print(fn)    except:        print('python')    finally:        print('最后的打印')trying_test ()

上述代碼運行輸出:

分母不能為0

[Errno 2] No such file or directory: "C:\Users\TEN\Desktop\'1.txt"

最后的打印

上述兩個嵌套的try-except被嵌套在第一個代碼中,精確的說就是兩個try-except被放在try代碼塊中,當然了實際的開發中我們也可與將要被嵌套的try-except放在except的代碼塊中。Python的traceback提供了一個print_exc()函數可以幫助我們打印一些異常的信息,有興趣的小伙伴可以查閱一下相關的文檔。

有的小伙伴注意到上述中有一個finally,這個finally的一個好處就是在異常拋出的之后,這個finally總會執行的,比如在諸如打開文件、寫數據到文件的操作失敗的時候就可以進行關閉文件的操作。

五、With-as

我們在看其他人代碼的時候,會看到這樣的代碼:with open(filename) as f 的樣式。使用with語句的好處,就是到達語句末尾時,會自動關閉文件,這就不需要使用try-except的方式捕捉異常進行關閉文件的操作了。

如果直接使用open()方法打開文件,如果出現異常,如讀取過程中文件不存在或異常,則直接出現錯誤,close方法無法執行,文件無法關閉的,我們來看看使用with open…的方式:

def open_file(filename):    try:        with open(filename) as f:            file = open(filename)            print('文件名:',file.name)    except OSError as E:        print('open file error')filename = r'C:\Users\TEN\Desktop\1.txt'open_file(filename)

六、異常類的定義

在實際的工程項目中,我們有時候需要定義一個區別于系統的異常類,還好python提供了一個可以自己定義異常類的方法,我們來看下面的代碼:

# 自定義異常類,繼承于Exception基類class Division_Error(Exception):    # 當輸出有誤時,拋出此異常    # 初始化    def __init__(self, value, name):        self.value = value        self.name = name    # 返回異常類對象的相關信息    def __str__(self):        if self.value % 2 != 0 and len(self.name) < 5:            return ("{}不是偶數,{}長度小于4".format(self.value,self.name) )try:    # 拋出異常    print('嘗試顯示拋出異常')    diverr = Division_Error(1,'name')    raise diverr    #或raise Division_Error(1,'name')'except Division_Error as diverr:    print('diverr: {}'.format(diverr))

上述代碼中自定了一個繼承于基類的Division_Error類,用于拋出一些異常,在try的代碼塊中,我們使用raise用于顯示的拋出異常。

七、總結

上述就是Python中異常處理的相關知識了,介紹了python中幾個異常的類型以及使用小例子具體介紹了他們的用法,接著我們介紹了異常的處理方法,這些方法在實際的項目中都非常的實用,小伙伴們可以參考其中的一些介紹進行實際的操作。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容