0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Python 異常的介紹以及異常處理的方法解析

馬哥Linux運維 ? 2018-01-31 14:20 ? 次閱讀

異常處理在任何一門編程語言里都是值得關(guān)注的一個話題,良好的異常處理可以讓你的程序更加健壯,清晰的錯誤信息更能幫助你快速修復(fù)問題。在Python中,和不分高級語言一樣,使用了try/except/finally語句塊來處理異常,如果你有其他編程語言的經(jīng)驗,實踐起來并不難。

什么是異常?

1.錯誤

從軟件方面來說,錯誤是語法或是邏輯上的。錯誤是語法或是邏輯上的。

語法錯誤指示軟件的結(jié)構(gòu)上有錯誤,導(dǎo)致不能被解釋器解釋或編譯器無法編譯。這些些錯誤必須在程序執(zhí)行前糾正。

當(dāng)程序的語法正確后,剩下的就是邏輯錯誤了。邏輯錯誤可能是由于不完整或是不合法的輸入所致;

在其它情況下,還可能是邏輯無法生成、計算、或是輸出結(jié)果需要的過程無法執(zhí)行。這些錯誤通常分別被稱為域錯誤和范圍錯誤。

當(dāng)python檢測到一個錯誤時,python解釋器就會指出當(dāng)前流已經(jīng)無法繼續(xù)執(zhí)行下去。這時候就出現(xiàn)了異常。

2.異常

對異常的最好描述是:它是因為程序出現(xiàn)了錯誤而在正??刂屏饕酝獠扇〉男袨?。

這個行為又分為兩個階段:首先是引起異常發(fā)生的錯誤,然后是檢測(和采取可能的措施)階段。

第一階段是在發(fā)生了一個異常條件(有時候也叫做例外的條件)后發(fā)生的。

只要檢測到錯誤并且意識到異常條件,解釋器就會發(fā)生一個異常。引發(fā)也可以叫做觸發(fā),拋出或者生成。解釋器通過它通知當(dāng)前控制流有錯誤發(fā)生。

python也允許程序員自己引發(fā)異常。無論是python解釋器還是程序員引發(fā)的,異常就是錯誤發(fā)生的信號

當(dāng)前流將被打斷,用來處理這個錯誤并采取相應(yīng)的操作。這就是第二階段。

對于異常的處理發(fā)生在第二階段,異常引發(fā)后,可以調(diào)用很多不同的操作。

可以是忽略錯誤(記錄錯誤但不采取任何措施,采取補救措施后終止程序。)或是減輕問題的影響后設(shè)法繼續(xù)執(zhí)行程序。

所有的這些操作都代表一種繼續(xù),或是控制的分支。關(guān)鍵是程序員在錯誤發(fā)生時可以指示程序如何執(zhí)行。

python用異常對象(exception object)來表示異常。遇到錯誤后,會引發(fā)異常。

如果異常對象并未被處理或捕捉,程序就會用所謂的回溯(traceback)終止執(zhí)行

異常處理

捕捉異??梢允褂胻ry/except語句。

try/except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常信息并處理。

如果你不想在異常發(fā)生時結(jié)束你的程序,只需在try里捕獲它。

語法:

以下為簡單的try....except...else的語法:

Try的工作原理是,當(dāng)開始一個try語句后,python就在當(dāng)前程序的上下文中作標(biāo)記,這樣當(dāng)異常出現(xiàn)時就可以回到這里,try子句先執(zhí)行,接下來會發(fā)生什么依賴于執(zhí)行時是否出現(xiàn)異常。

如果當(dāng)try后的語句執(zhí)行時發(fā)生異常,python就跳回到try并執(zhí)行第一個匹配該異常的except子句,異常處理完畢,控制流就通過整個try語句(除非在處理異常時又引發(fā)新的異常)。

如果在try后的語句里發(fā)生了異常,卻沒有匹配的except子句,異常將被遞交到上層的try,或者到程序的最上層(這樣將結(jié)束程序,并打印缺省的出錯信息)。

如果在try子句執(zhí)行時沒有發(fā)生異常,python將執(zhí)行else語句后的語句(如果有else的話),然后控制流通過整個try語句。

使用except而不帶任何異常類型

你可以不帶任何異常類型使用except,如下實例:

以上方式try-except語句捕獲所有發(fā)生的異常。但這不是一個很好的方式,我們不能通過該程序識別出具體的異常信息。因為它捕獲所有的異常。

使用except而帶多種異常類型

你也可以使用相同的except語句來處理多個異常信息,如下所示:

try-finally 語句

try-finally 語句無論是否發(fā)生異常都將執(zhí)行最后的代碼。

當(dāng)在try塊中拋出一個異常,立即執(zhí)行finally塊代碼。

finally塊中的所有語句執(zhí)行后,異常被再次觸發(fā),并執(zhí)行except塊代碼。

參數(shù)的內(nèi)容不同于異常。

下面來看一個實例:

基于Python 異常的介紹以及異常處理的方法解析

點擊查看大圖

總結(jié)如下:

except語句不是必須的,finally語句也不是必須的,但是二者必須要有一個,否則就沒有try的意義了。

except語句可以有多個,Python會按except語句的順序依次匹配你指定的異常,如果異常已經(jīng)處理就不會再進入后面的except語句。

except語句可以以元組形式同時指定多個異常,參見實例代碼。

except語句后面如果不指定異常類型,則默認(rèn)捕獲所有異常,你可以通過logging或者sys模塊獲取當(dāng)前異常。

如果要捕獲異常后要重復(fù)拋出,請使用raise,后面不要帶任何參數(shù)或信息。

不建議捕獲并拋出同一個異常,請考慮重構(gòu)你的代碼。

不建議在不清楚邏輯的情況下捕獲所有異常,有可能你隱藏了很嚴(yán)重的問題。

盡量使用內(nèi)置的異常處理語句來 替換try/except語句,比如with語句,getattr()方法。

經(jīng)驗案例

傳遞異常 re-raise Exception捕捉到了異常,但是又想重新引發(fā)它(傳遞異常),使用不帶參數(shù)的raise語句即可:

在Python2中,為了保持異常的完整信息,那么你捕獲后再次拋出時千萬不能在raise后面加上異常對象,否則你的trace信息就會從此處截斷。以上是最簡單的重新拋出異常的做法。

還有一些技巧可以考慮,比如拋出異常前對異常的信息進行更新。

如果你有興趣了解更多,建議閱讀這篇博客。

http://www.ianbicking.org/blog/2007/09/re-raising-exceptions.html

Python3對重復(fù)傳遞異常有所改進,你可以自己嘗試一下,不過建議還是同上。

Exception 和 BaseException

當(dāng)我們要捕獲一個通用異常時,應(yīng)該用Exception還是BaseException?我建議你還是看一下 官方文檔說明,這兩個異常到底有啥區(qū)別呢? 請看它們之間的繼承關(guān)系。

從Exception的層級結(jié)構(gòu)來看,BaseException是最基礎(chǔ)的異常類,Exception繼承了它。BaseException除了包含所有的Exception外還包含了SystemExit,KeyboardInterrupt和GeneratorExit三個異常。

有此看來你的程序在捕獲所有異常時更應(yīng)該使用Exception而不是BaseException,因為另外三個異常屬于更高級別的異常,合理的做法應(yīng)該是交給Python的解釋器處理。

except Exception as e和 except Exception, e

代碼示例如下:

在Python2的時代,你可以使用以上兩種寫法中的任意一種。在Python3中你只能使用第一種寫法,第二種寫法被廢棄掉了。第一個種寫法可讀性更好,而且為了程序的兼容性和后期移植的成本,請你也拋棄第二種寫法。

raise “Exception string”

把字符串當(dāng)成異常拋出看上去是一個非常簡潔的辦法,但其實是一個非常不好的習(xí)慣。

上面的語句如果拋出異常,那么會是這樣的:

基于Python 異常的介紹以及異常處理的方法解析

這在Python2.4以前是可以接受的做法,但是沒有指定異常類型有可能會讓下游沒辦法正確捕獲并處理這個異常,從而導(dǎo)致你的程序掛掉。簡單說,這種寫法是是封建時代的陋習(xí),應(yīng)該扔了。

使用內(nèi)置的語法范式代替try/except

Python 本身提供了很多的語法范式簡化了異常的處理,比如for語句就處理的StopIteration異常,讓你很流暢地寫出一個循環(huán)。

with語句在打開文件后會自動調(diào)用finally中的關(guān)閉文件操作。我們在寫Python代碼時應(yīng)該盡量避免在遇到這種情況時還使用try/except/finally的思維來處理。

再比如,當(dāng)我們需要訪問一個不確定的屬性時,有可能你會寫出這樣的代碼:

其實你可以使用更簡單的getattr()來達到你的目的。

最佳實踐

最佳實踐不限于編程語言,只是一些規(guī)則和填坑后的收獲。

1.只處理你知道的異常,避免捕獲所有異常然后吞掉它們。

2.拋出的異常應(yīng)該說明原因,有時候你知道異常類型也猜不出所以然的。

3.避免在catch語句塊中干一些沒意義的事情。

4.不要使用異常來控制流程,那樣你的程序會無比難懂和難維護。

5.如果有需要,切記使用finally來釋放資源。

6如果有需要,請不要忘記在處理異常后做清理工作或者回滾操作。

異常速查表

基于Python 異常的介紹以及異常處理的方法解析

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編程語言
    +關(guān)注

    關(guān)注

    10

    文章

    1916

    瀏覽量

    34369
  • 異常處理
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    7260
  • python
    +關(guān)注

    關(guān)注

    53

    文章

    4752

    瀏覽量

    84066

原文標(biāo)題:一文掌握 Python 異常處理的所有知識點

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Python異常處理和單元測試簡介

    程序越復(fù)雜,出現(xiàn)異常的概率越大,如何在程序崩潰之前,捕捉異常,預(yù)判異常?項目越大,需要測試的內(nèi)容越多,如何快速有效地測試?
    發(fā)表于 09-04 16:27 ?400次閱讀
    <b class='flag-5'>Python</b><b class='flag-5'>異常</b><b class='flag-5'>處理</b>和單元測試簡介

    如何有效的處理空指針異常

    地遇到這個問題。 那么我們應(yīng)該如何有效且優(yōu)雅的處理空指針異常呢? 下面了不起將詳細的介紹這個處理方案。 1、什么是空指針異常? 空指針
    的頭像 發(fā)表于 09-30 10:25 ?1341次閱讀

    arm異常處理方法

    ARM異常處理:只要正常的程序流被暫時中止,處理器就進入異常模式。例如響應(yīng)一個來自外設(shè)的中斷。在處理異常
    發(fā)表于 04-20 10:52

    python常見異常類型

    ,我們統(tǒng)稱為異常。正常情況下,異常都不會被程序處理,而是以錯誤信息的形式展現(xiàn)出來。異常有很多種類型,Python內(nèi)置了幾十種常見的
    發(fā)表于 03-04 16:59

    python如何主動拋出異常和捕獲異常

    最多會執(zhí)行一個處理程序。當(dāng)代碼 A 在運行中拋出了異常時,Python 解釋器會逐行運行代碼,如果拋出的異常是 exception1 那么后面直接運行代碼B,運行完 B 后,就不會再判
    發(fā)表于 03-04 17:10

    基于案例推理的工作流異常處理研究

    對工作流的異常和案例推理(Case - Based Reasoning,簡稱CBR)的機制進行了介紹,給出了一個應(yīng)用CBR 技術(shù)進行異常處理的工作流模型,并研究了應(yīng)用CBR
    發(fā)表于 06-15 10:20 ?14次下載

    基于VxWorks的異常處理的研究和實現(xiàn)

    闡述了嵌入式軟件系統(tǒng)中異常處理的必要性,然后基于嵌入式實時操作系統(tǒng)VxWorks,介紹了一種與具體處理器類型無關(guān)的異常
    發(fā)表于 01-11 09:13 ?23次下載

    java異常處理的設(shè)計與重構(gòu)

    在程序設(shè)計中,進行異常處理是非常關(guān)鍵和重要的一部分。一個程序的異常處理框架的好壞直接影響到整個項目的代碼質(zhì)量以及后期維護成本和難度。試想一下
    發(fā)表于 09-27 15:40 ?1次下載
    java<b class='flag-5'>異常</b><b class='flag-5'>處理</b>的設(shè)計與重構(gòu)

    python如何捕獲異常和主動拋出異常

    python如何主動拋出異常和捕獲異常 1. 如何拋出異常? 異常的產(chǎn)生有兩種來源: 一種是程序自動拋出,比如 1/0 會自動拋出 Zero
    的頭像 發(fā)表于 03-04 17:09 ?9591次閱讀

    替代try catch處理異常的優(yōu)雅方式

    不過跟異常處理相關(guān)的只有注解@ExceptionHandler,從字面上看,就是 異常處理器 的意思,其實際作用也是:若在某個Controller類定義一個
    的頭像 發(fā)表于 10-26 10:18 ?1008次閱讀

    發(fā)電機安裝過程中轉(zhuǎn)軸絕緣異常異常的原因及處理方法

    通過對一起發(fā)電機安裝過程中轉(zhuǎn)軸絕緣異常事件的檢查,闡述了轉(zhuǎn)軸絕緣異常對發(fā)電機安全穩(wěn)定運行的影響,分析了轉(zhuǎn)軸絕緣異常的原因,介紹了檢查處理
    的頭像 發(fā)表于 02-02 10:04 ?5033次閱讀

    Python-模塊、包、異常

    * 程序運行時,如果Python 解釋器遇到了錯誤,會停止程序運行,并且提示錯誤信息,**這就是異常**,* 程序停止執(zhí)行并提示錯誤信息的動作,稱為 **拋出異常**
    的頭像 發(fā)表于 02-16 15:40 ?631次閱讀
    <b class='flag-5'>Python</b>-模塊、包、<b class='flag-5'>異常</b>

    Python中的異常機制(一)

    前言 哈嘍, 大家好, 我是了不起! 歡迎大家來觀看了不起的冒險之旅. 為了方便起見, 文中以小知為名. 講述了不起在Python異世界的冒險之旅. 白天冒險, 晚上學(xué)習(xí). 小知可是身體和心理沒有
    的頭像 發(fā)表于 05-11 18:17 ?683次閱讀
    <b class='flag-5'>Python</b>中的<b class='flag-5'>異常</b>機制(一)

    Python中的異常機制(二)

    ?[as??e]: ?異常處理語句塊 注意事項: try 塊包含著可能引發(fā)異常的代碼, except 塊則用來捕捉和處理發(fā)生的異常 執(zhí)行的時
    的頭像 發(fā)表于 05-11 18:20 ?841次閱讀

    直流屏系統(tǒng)的操作、查詢及異常處理方法

    直流屏系統(tǒng)的操作、查詢及異常處理方法
    的頭像 發(fā)表于 12-15 10:29 ?634次閱讀
    直流屏系統(tǒng)的操作、查詢及<b class='flag-5'>異常</b><b class='flag-5'>處理</b><b class='flag-5'>方法</b>