- 來源 | 愿碼(ChainDesk.CN)內容編輯
- 愿碼Slogan | 連接每個程序員的故事
- 網站 | http://chaindesk.cn
- 愿碼愿景 | 打造全學科IT系統免費課程,助力小白用戶、初級工程師0成本免費系統學習、低成本進階,幫助BAT一線資深工程師成長并利用自身優勢創造睡后收入。
- 官方公眾號 | 愿碼 | 愿碼服務號 | 區塊鏈部落
- 免費加入愿碼全思維工程師社群 | 任一公眾號回復“愿碼”兩個字獲取入群二維碼
本文閱讀時長:10min
本文所涉及知識點
- Python中有哪些異常 ?
- 使用try ... except子句控制程序流
- 通過處理異常來處理常見問題
- 創建和使用自定義異常類
在直接進入代碼并解決這些問題之前,讓我們首先了解異常是什么以及處理異常是什么意思。
什么是異常?
異常是Python中的對象。它為我們提供了有關在程序執行期間檢測到的錯誤的信息。在調試應用程序時注意到的錯誤是 未處理的異常, 因為我們沒有這些異常。在本文后面,您將學習處理這些異常的技巧。
在早期回溯中看到的ValueError和IndexError異常是Python中內置異常類型的示例 。在下一節中,您將了解Python支持的其他一些內置異常 。
最常見的異常
讓我們快速回顧一些最常遇到的異常。最簡單的方法是嘗試運行一些錯誤的代碼,讓它報告錯誤回溯的問題!啟動Python解釋器并編寫以下代碼:
以下是一些異常情況:
正如您所看到的,代碼的每一行都會拋出一個帶有異常類型的錯誤回溯(突出顯示)。這些是Python中的一些內置異常。Python提供BaseException作為所有內置異常的基類。但是,大多數內置異常不直接繼承BaseException。相反,它們是從一個名為Exception的類派生而來的,而這個類又繼承自BaseException。處理程序退出的內置異常(例如,SystemExit)直接從BaseException派生。您還可以創建自己的異常類作為Exception的子類。您將在本文后面了解到這一點。
異常處理
到目前為止,我們已經看到了異常的發生方式 現在,是時候學習如何使用try ... except子句來處理這些異常。以下偽代碼顯示了try ... except子句的一個非常簡單的示例:
我們來看看前面的代碼片段:
· 首先,程序嘗試執行try子句中的代碼。
· 在執行期間,如果出現錯誤(如果發生異常),它將跳出此try子句。try塊中的其余代碼不會被執行。
· 然后,它在except子句中查找適當的異常處理程序并執行它。
這里使用的 except子句是通用的。它將捕獲try子句中發生的所有類型的異常。而不是擁有這個“全能”處理程序,更好的做法是捕獲您預期的錯誤并編寫特定于這些錯誤的異常處理代碼。例如,try子句中的代碼可能會拋出AssertionError。您可以編寫特定的異常處理程序,而不是使用universal except子句,如下所示:
在這里,我們有一個except子句專門處理AssertionError。它還意味著除了AssertionError之外的任何錯誤都將作為未處理的異常漏掉。為此,我們需要使用不同的異常處理程序定義多個except子句。但是,在任何時候,只會調用一個異常處理程序。用一個例子可以更好地解釋這一點。我們來看看下面的代碼片段:
該試塊調用solve_something() 。此函數接受一個數字作為用戶輸入,并斷言該數字大于零。如果斷言失敗,它會直接跳轉到處理程序,但AssertionError除外。
在另一個場景中,如果> 0,則執行solve_something()中的其余代碼。您會注意到未定義變量x,這會導致NameError。此異常由另一個異常子句處理,但NameError除外。同樣,您可以為預期的錯誤定義特定的異常處理程序。
提高并重新提出異常
Python中的raise關鍵字用于強制發生異常。換句話說,它引發了一個異常。語法很簡單; 只需打開Python解釋器并輸入:
>>> raise AssertionError("some error message")
這會產生以下錯誤回溯:
Traceback (most recent call last):
File "", line 1, in
AssertionError : some error message
在某些情況下,我們需要重新引發異常。假設,在try子句中,您有一個將數字除以零的表達式。在普通算術中,這個表達沒有意義。這是一個錯誤!這會導致程序引發一個名為ZeroDivisionError的異常。如果沒有異常處理代碼,程序將只打印錯誤消息并終止。
如果您希望將此錯誤寫入某個日志文件然后終止該程序,該怎么辦?在這里,您可以使用except子句首先記錄錯誤。然后,使用不帶任何參數的raise關鍵字來重新引發異常。異常將在堆棧中向上傳播。在此示例中,它終止程序。可以使用raise關鍵字重新引發異常而不使用任何參數。
這是一個示例,顯示如何重新引發異常:
可以看出,在解決a / b表達式時,會出現zeroexception的adivision。這是因為變量b的值設置為0。出于說明目的,我們假設此錯誤沒有特定的異常處理程序。因此,我們將使用general except子句,在記錄錯誤后重新引發異常。如果您想自己嘗試,只需在新的Python文件中編寫前面說明的代碼,然后從終端窗口運行它。以下屏幕截圖顯示了上述代碼的輸出:
try ... except
可以在try ... except子句中指定可選的else塊。在其他的只發生ifno異常塊被執行的嘗試......除了條款。語法如下:
在其他塊的前執行最后條款,我們將在接下來的學習。
finally......clean it up!
還有其他東西可以添加到try ...除了... else story:一個可選的finally子句。顧名思義,此子句中的代碼在關聯的try ... except塊的末尾執行。無論是否引發異常,finally子句(如果指定)將在try ... except子句的末尾執行。想象一下它是由Python提供的全天候保證!以下代碼段顯示了finally塊的運行情況:
運行這個簡單的代碼將產生以下輸出:
$ python finally_example1.py
Enter a number: -1
Uh oh..Assertion Error.
Do some special cleanup
輸出中的最后一行是finally子句中的print語句。
帶有和不帶finally子句的代碼片段如下面的屏幕截圖所示。即使except子句指示代碼從函數返回,也確保finally子句中的代碼最終執行。
在最后條款通常用于離開功能之前執行清理任務。示例用例是關閉數據庫連接或文件。但請注意,為此,您還可以在Python中使用with語句。
編寫一個新的異常類
創建一個從Exception派生的新異常類是微不足道的。打開Python解釋器并創建以下類:
>>> class GameUnitError(Exception):
... pass
...
>>>
就這樣!我們有一個新的異常類GameUnitError,可以部署了。如何測試此異常?在Python解釋器中鍵入以下代碼行:
>>> raise GameUnitError("ERROR: some problem with game unit")
引發新創建的異常將打印以下回溯:
>>> raise GameUnitError("ERROR: some problem with game unit")
Traceback (most recent call last):
File "", line 1, in
__main__.GameUnitError: ERROR: some problem with game unit
將GameUnitError類復制到其自己的模塊gameuniterror.py中,并將其保存在與attackoftheorcs_v1_1.py相同的目錄中。
接下來,更新attackoftheorcs_v1_1.py文件以包含以下更改:
首先,在文件的開頭添加以下import語句:
from gameuniterror import GameUnitError
第二個變化是在AbstractGameUnit.heal方法中。更新后的代碼顯示在以下代碼段中。觀察高亮代碼,只要提出的價值自定義異常self.health_meter超過的self.max_hp。
通過這兩個更改,運行之前創建的heal_exception_example.py。您將看到引發新的異常,如以下屏幕截圖所示:
擴展異常類
我們可以用GameUnitError類做更多的事情嗎?當然!就像任何其他類一樣,我們可以定義屬性并使用它們。讓我們進一步擴展這個課程。在修改后的版本中,它將接受一個額外的參數和一些預定義的錯誤代碼。更新的GameUnitError類顯示在以下屏幕截圖中:
我們來看看前面屏幕截圖中的代碼:
· 首先,它調用Exception超類的__init__方法,然后定義一些額外的實例變量。
· 一個新的dictionary對象self。error_dict將錯誤整數代碼和錯誤信息保存為鍵值對。
· 該self.error_message存儲有關根據提供的錯誤代碼當前錯誤的信息。
· 在嘗試......除了子句確保error_dict實際上已經由指定的鍵碼的說法。它不在except子句中,我們只是檢索默認錯誤代碼為000的值。
到目前為止,我們已經對GameUnitError類和AbstractGameUnit.heal方法進行了更改。我們還沒有完成。拼圖的最后一塊是修改主要在程序heal_exception_example.py文件。代碼顯示在以下屏幕截圖中:
我們來看看代碼:
· 由于heal_by值太大,try子句中的heal方法會引發GameUnitError異常。
· new except子句處理GameUnitError異常,就像任何其他內置異常一樣。
· 在except子句中,我們有兩個print語句。第一個打印health_meter> max_hp!(回想一下,當在heal方法中引發此異常時,此字符串被作為GameUnitError實例的第一個參數給出)。第二個print語句檢索并打印GameUnitError實例的error_message屬性。
我們已經做好了所有的改變。我們可以在終端窗口中運行此示例:
$ python heal_exception_example.py
該程序的輸出顯示在以下屏幕截圖中:
在這個簡單的例子中,將錯誤信息打印到控制臺。您可以進一步將詳細錯誤日志寫入文件,并跟蹤應用程序運行時生成的所有錯誤消息。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
