總結Python異常處理的三個重要知識點

我曾經幫很多人修過電腦,排除硬件問題、排除系統問題、網絡問題等等。

在修電腦的過程中比如電腦無法開機,我就會假定它某個配件已經壞掉了,就先從電源開始排查起、CPU、內存、主板等等一個一個的測試,看看究竟是哪一個配件有問題。

如果操作系統系統速度變慢同樣也可以用類似的辦法,先看當前佔用進程有沒有不必要啓動的、是否有病毒、系統是否沒有優化等等。

實際上在編程過程中,我們一樣會假定某段代碼某個功能可能會出現問題的方式來編寫我們的代碼。

今天我們主要來講講Python語言的異常處理相關知識。

本章知識點:

  • 異常捕獲

  • 主動拋出異常

  • 自定義異常

異常捕獲:

首先我們來看一個例子:

我通過 print(a) 讓Python解釋器給我報了一個異常,其中包含錯誤信息的所有上下文信息,代碼路徑、錯誤代碼內容、錯誤信息等等。

print(a)這個語句錯誤的原因是在於a這個變量沒有定義 (NameError: name ‘a’ is not defined),這在我寫代碼之前就清楚。

然而在實際編程過程中,隨着代碼量的增加,我們有的時候並不確定某個變量是否已經被賦值成功,如果變量未被成功的賦值,程序還是按原計劃對其進行操作時可能就會直接報錯。

要解決這個問題有兩個辦法:

  1. 對變量進行操作(例如加減法)之前檢查它的值是否已經存在,如果不存在,就告訴用戶

  2. 捕獲該異常,並且告訴用戶

這兩種辦法的結果其實都是會告訴用戶錯誤信息,在結果上並沒有太大的變化,今天我們主要講第二種,異常自動捕獲的方式。

現在我們改造一下剛纔的代碼,把異常捕獲到然後自定義處理方式:

以上的代碼例子展示我們通過異常捕獲 try except的語法把錯誤捕獲到,並且自定義了其輸出內容。

讓我們來解釋一下這段代碼:

  • try用於定義一個異常捕獲的語法塊。

  • try縮進的區塊裏,我們可以正常寫我們想要實現的代碼。

  • except區塊裏,我們定義瞭如果程序報錯後所要執行的代碼,在本例子中就是直接打印報錯信息 (報錯信息:name ‘a’ is not defined)。

  • except後面的Exception as e 的用處是用於定義錯誤信息類型(Exception),並且將錯誤信息賦值給變量e。

通過在代碼任意位置使用try…except語法,我們可以設置多個try…except的代碼塊,如果在try中程序正常執行沒有報錯,那麼程序就會跳過except區塊,正常執行之後的代碼。

異常類型:

我們剛纔用到Exception這個異常類型,它在Python中是常規錯誤的基類,如果我們對可能出錯的類型不能確定時就可以使用到它,但是一般不建議這麼做

不直接使用Exception的理由是我們在捕獲到異常時,總是希望能夠對異常進行明確的報錯或者處理,如果所有錯誤都是Exception類型,我們其實也不知道程序究竟是在哪裏出了錯。

舉個例子來說明這個問題。

通過上面這個例子我們可以學到兩件事情

  1. except和try是一對多的,有一個try語句,可以有1個或多個 except語句,其用處是定義任意個異常類型和相關的處理代碼

  2. 當異常捕獲發生後,程序會中斷執行,停留在第一個異常報錯的位置。在本例子中因爲我們import xxx實際上是引入了一個不存在的模塊名,所以程序報錯 No module named ‘xxx’,其錯誤類型是ImportError

現在我們嘗試把import xxx去掉試試。

現在程序報了類型錯誤(TypeError),因爲int類型的數據無法和str類型的數字進行加法操作。

下面我給一個Python的常見異常錯誤類型表,供大家參考。

主動拋出異常:

上面我們講到了Python如何被動捕獲異常,現在我們來講講主動拋出異常的方法。

爲什麼要主動拋出異常?

通常我們通過try except捕獲的異常叫做被動捕獲,它其實是需要程序員進行處理的,比如對錯誤的變量內容做一些改正讓其繼續執行。但是主動拋出異常通常不需要再進行處理,程序員已經確定這個地方必須拋出異常給用戶,並且中斷程序執行,基於這種情況下程序員就不用再對異常進行處理了。

來看一個例子:

在這段代碼裏,我們定義了a爲一個整型的數字。

然後通過instance()內部函數判斷a如果不是字符串類型的情況下,就通過raise語句主動拋出一個異常,報錯內容也是我們自定義的,其作用就是直接告訴用戶,數據出錯了。

有朋友會提一個問題,你自己定義的a = 1,它明明是整型數字,你還拿去判斷它是不是字符串,這不是多此一舉嗎?它是不是字符串你心裏沒點數嗎?

沒錯,之所以你會有這個問題是因爲我們的例子太簡單,假設變量a的內容是來自於另一個模塊呢?或者是來自於爬蟲從網絡上抓取下來的數據?這個時候我們根本不知道a可能是什麼內容,那麼就必須用到異常處理機制了。

raise的語法很簡單:

raise [exceptionName [(reason)]]

在它後面跟上想要拋出的異常類型即可,如果有必要寫上錯誤內容的話,就傳進去:

raise ValueError(“a必須是字符串”)

另外raise語句其實也可以和 try except結合起來使用:

上面這個例子展現了程序如何主動拋出異常,再由except捕獲並打印錯誤信息。

自定義異常:

其實我們剛纔瞭解到所有異常錯誤類型其實都是一個類 (class ),那麼我們同樣可以自定義一個異常類,以便於在程序裏使用。

通過以上的代碼例子:

  • 我們自定義了一個異常類,叫做CustomerError,繼承自BaseException這個Python異常錯誤類型的基類

  • 然後定義其__init__方法,並用一個變量接受傳入的錯誤信息。

  • __init__方法裏可以什麼都不做,用一個pass佔位即可,因爲CustomerError類是繼承自BaseException的,它天生具有BaseException的所有特性。

  • 最後我們拋出一個CustomerError異常,並傳了一個字符串內容"自定義異常"進去,由except 捕獲到這個異常並輸出異常內容。

總結:

通過自定義異常,我們可以不用拘泥於Python自帶的異常錯誤類型,定義更多自己想要的錯誤類型,精確的控制出錯的時機和處理方式。

最後通過一個思維導圖來展示異常處理的相關知識點。

正在學習的小夥伴,推薦我們的Python學習扣qun:784758214 ,看看前輩們是如何學習的!從基礎的python腳本到web開發、爬蟲、django、數據挖掘等【PDF,實戰源碼】,零基礎到項目實戰的資料都有整理。送給每一位python的小夥伴!每天都有大牛定時講解Python技術,分享一些學習的方法和需要注意的小細節,點擊加入我們的 python學習者聚集地

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章