Python 異常處理的實(shí)例詳解
Python 異常處理的實(shí)例詳解
與許多面向?qū)ο笳Z(yǔ)言一樣,Python 具有異常處理,通過(guò)使用 try...except 塊來(lái)實(shí)現(xiàn)。
Note: Python v s. Java 的異常處理
Python 使用 try...except 來(lái)處理異常,使用 raise 來(lái)引發(fā)異常。Java 和 C++ 使用 try...catch 來(lái)處理異常,使用 throw 來(lái)引發(fā)異常。
異常在 Python 中無(wú)處不在;實(shí)際上在標(biāo)準(zhǔn) Python 庫(kù)中的每個(gè)模塊都使用了它們,并且 Python 自已會(huì)在許多不同的情況下引發(fā)它們。在整本書中你已經(jīng)再三看到它們了。
• 使用不存在的字典關(guān)鍵字 將引發(fā) KeyError 異常。
• 搜索列表中不存在的值 將引發(fā) ValueError 異常。
• 調(diào)用不存在的方法 將引發(fā) AttributeError 異常。
• 引用不存在的變量 將引發(fā) NameError 異常。
• 未強(qiáng)制轉(zhuǎn)換就混用數(shù)據(jù)類型 將引發(fā) TypeError 異常。
在這些情況下,我們都在簡(jiǎn)單地使用 Python IDE:一個(gè)錯(cuò)誤發(fā)生了,異常被打印出來(lái) (取決于你的 IDE,可能會(huì)有意地以一種刺眼的紅色形式表示),這便是。這叫做未處理異常;當(dāng)異常被引發(fā)時(shí),沒(méi)有代碼來(lái)明確地關(guān)注和處理它,所以異常被傳給置在 Python 中的缺省的處理,它會(huì)輸出一些調(diào)試信息并且終止運(yùn)行。在 IDE 中,這不是什么大事,但是如果發(fā)生在你真正的 Python 程序運(yùn)行的時(shí)候,整個(gè)程序?qū)?huì)終止。
然而,一個(gè)異常不一定會(huì)引起程序的完全崩潰。當(dāng)異常引發(fā)時(shí),可以被處理掉。有時(shí)候一個(gè)異常實(shí)際是因?yàn)榇a中的 bug (比如使用一個(gè)不存在的變量),但是許多時(shí)候,一個(gè)異常是可以預(yù)見的。如果你打開一個(gè)文件,它可能不存在。如果你連接一個(gè)數(shù)據(jù)庫(kù),它可能不可連接或沒(méi)有訪問(wèn)所需的正確的安全證書。如果知道一行代碼可能會(huì)引發(fā)異常,你應(yīng)該使用一個(gè) try...except 塊來(lái)處理異常。
1. 打開一個(gè)不存在的文件
>>> fsock = open("/notthere", "r") (1) Traceback (innermost last): File "<interactive input>", line 1, in ? IOError: [Errno 2] No such file or directory: '/notthere' >>> try: ... fsock = open("/notthere") (2) ... except IOError: (3) ... print "The file does not exist, exiting gracefully" ... print "This line will always print" (4) The file does not exist, exiting gracefully This line will always print
(1) 使用內(nèi)置 open 函數(shù),我們可以試著打開一個(gè)文件來(lái)讀取 (在下一節(jié)有關(guān)于open 的更多內(nèi)容)。但是那個(gè)文件不存在,所以這樣就引發(fā) IOError 異常。因?yàn)槲覀儧](méi)有提供任何顯式的對(duì) IOError 異常的檢查,Python 僅僅打印出某個(gè)關(guān)于發(fā)生了什么的調(diào)試信息,然后終止。
(2) 我們?cè)噲D打開同樣不存在的文件,但是這次我們?cè)谝粋€(gè) try...except 內(nèi)來(lái)執(zhí)行它。
(3) 當(dāng) open 方法引發(fā) IOError 異常時(shí),我們已經(jīng)準(zhǔn)備好處理它了。except IOError: 行捕捉異常,接著執(zhí)行我們自已的代碼塊,這個(gè)代碼塊在本例中只是打印出更令人愉快的錯(cuò)誤信息。
(4) 一旦異常被處理了,處理通常在 try...except 塊之后的第一行繼續(xù)進(jìn)行。注意這一行將總是打印出來(lái),無(wú)論異常是否發(fā)生。如果在你的根目錄下確實(shí)有一個(gè)叫 notthere 的文件,對(duì) open 的調(diào)用將成功,except 子句將忽略,并且最后一行仍將執(zhí)行。
異常可能看上去不友好 (畢竟,如果你不捕捉異常,整個(gè)程序?qū)⒈罎?,但是考慮一下別的方法。你該不會(huì)希望獲得一個(gè)指向不存在的文件的對(duì)象吧?不管怎么樣你都得檢查它的有效性,而且如果你忘記了,你的程序?qū)?huì)在下面某個(gè)地方給出奇怪的錯(cuò)誤,這樣你將不得不追溯到源程序。我確信你做過(guò)這種事;這可并不有趣。使用異常,一發(fā)生錯(cuò)誤,你就可以在問(wèn)題的源頭通過(guò)標(biāo)準(zhǔn)的方法來(lái)處理它們。
2. 為其他用途使用異常
除了處理實(shí)際的錯(cuò)誤條件之外,對(duì)于異常還有許多其它的用處。在標(biāo)準(zhǔn) Python 庫(kù)中一個(gè)普通的用法就是試著導(dǎo)入一個(gè)模塊,然后檢查是否它能使用。導(dǎo)入一個(gè)并不存在的模塊將引發(fā)一個(gè) ImportError 異常。你可以使用這種方法來(lái)定義多級(jí)別的功能――依靠在運(yùn)行時(shí)哪個(gè)模塊是有效的,或支持多種平臺(tái) (即平臺(tái)特定代碼被分離到不同的模塊中)。你也能通過(guò)創(chuàng)建一個(gè)從內(nèi)置的 Exception 類繼承的類定義你自己的異常,然后使用 raise 命令引發(fā)你的異常。如果你對(duì)此感興趣,請(qǐng)看進(jìn)一步閱讀的部分。
下面的例子演示了如何使用異常支持特定平臺(tái)功能。代碼來(lái)自 getpass 模塊,一個(gè)從用戶獲得口令的封裝模塊。獲得口令在 UNIX、Windows 和 Mac OS 平臺(tái)上的實(shí)現(xiàn)是不同的,但是這個(gè)代碼封裝了所有的不同之處。
# Bind the name getpass to the appropriate function try: import termios, TERMIOS (1) except ImportError: try: import msvcrt (2) except ImportError: try: from EasyDialogs import AskPassword (3) except ImportError: getpass = default_getpass (4) else: (5) getpass = AskPassword else: getpass = win_getpass else: getpass = unix_getpass
(1) termios 是 UNIX 獨(dú)有的一個(gè)模塊,它提供了對(duì)于輸入終端的底層控制。如果這個(gè)模塊無(wú)效 (因?yàn)樗辉谀愕南到y(tǒng)上,或你的系統(tǒng)不支持它),則導(dǎo)入失敗,Python 引發(fā)我們捕捉的 ImportError 異常。
(2) OK,我們沒(méi)有 termios,所以讓我們?cè)囋?msvcrt,它是 Windows 獨(dú)有的一個(gè)模塊,可以提供在 Microsoft Visual C++ 運(yùn)行服務(wù)中的許多有用的函數(shù)的一個(gè) API。如果導(dǎo)入失敗,Python 會(huì)引發(fā)我們捕捉的 ImportError 異常。
(3) 如果前兩個(gè)不能工作,我們?cè)囍鴱?EasyDialogs 導(dǎo)入一個(gè)函數(shù),它是 Mac OS 獨(dú)有的一個(gè)模塊,提供了各種各樣類型的彈出對(duì)話框。再一次,如果導(dǎo)入失敗,Python 會(huì)引發(fā)一個(gè)我們捕捉的 ImportError 異常。
(4) 這些平臺(tái)特定的模塊沒(méi)有一個(gè)有效 (有可能,因?yàn)?Python 已經(jīng)移植到了許多不同的平臺(tái)上了),所以我們需要回頭使用一個(gè)缺省口令輸入函數(shù) (這個(gè)函數(shù)定義在 getpass 模塊中的別的地方)。注意我們?cè)谶@里所做的:我們將函數(shù) default_getpass 賦給變量 getpass。如果你讀了官方 getpass 文檔,它會(huì)告訴你 getpass 模塊定義了一個(gè) getpass 函數(shù)。它是這樣做的:通過(guò)綁定 getpass 到正確的函數(shù)來(lái)適應(yīng)你的平臺(tái)。然后當(dāng)你調(diào)用 getpass 函數(shù)時(shí),你實(shí)際上調(diào)用了平臺(tái)特定的函數(shù),是這段代碼已經(jīng)為你設(shè)置好的。你不需要知道或關(guān)心你的代碼正運(yùn)行在何種平臺(tái)上;只要調(diào)用 getpass,則它總能正確處理。
(5) 一個(gè) try...except 塊可以有一條 else 子句,就像 if 語(yǔ)句。如果在 try 塊中沒(méi)有異常引發(fā),然后 else 子句被執(zhí)行。在本例中,那就意味著如果 from EasyDialogs import AskPassword 導(dǎo)入可工作,所以我們應(yīng)該綁定 getpass 到 AskPassword 函數(shù)。其它每個(gè) try...except 塊有著相似的 else 子句,當(dāng)我們發(fā)現(xiàn)一個(gè) import 可用時(shí),就綁定 getpass 到適合的函數(shù)。
如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
通過(guò)python實(shí)現(xiàn)windows桌面截圖代碼實(shí)例
這篇文章主要介紹了python實(shí)現(xiàn)windows桌面截圖代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Python定時(shí)執(zhí)行程序問(wèn)題(schedule)
這篇文章主要介紹了Python定時(shí)執(zhí)行程序問(wèn)題(schedule),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Python操作dict時(shí)避免出現(xiàn)KeyError的幾種解決方法
這篇文章主要介紹了Python操作dict時(shí)避免出現(xiàn)KeyError的幾種解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Python實(shí)現(xiàn)平行坐標(biāo)圖的兩種方法小結(jié)
今天小編就為大家分享一篇Python實(shí)現(xiàn)平行坐標(biāo)圖的兩種方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07python基礎(chǔ)教程項(xiàng)目二之畫幅好畫
這篇文章主要為大家詳細(xì)介紹了python基礎(chǔ)教程項(xiàng)目二之畫幅好畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04基于python實(shí)現(xiàn)藍(lán)牙通信代碼實(shí)例
這篇文章主要介紹了基于python實(shí)現(xiàn)藍(lán)牙通信代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Python+AutoIt實(shí)現(xiàn)界面工具開發(fā)過(guò)程詳解
這篇文章主要介紹了Python+AutoIt實(shí)現(xiàn)界面工具開發(fā)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08