亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

對(duì)于Python異常處理慎用“except:pass”建議

 更新時(shí)間:2015年04月02日 14:58:29   作者:(StackOverflow)  
這篇文章主要介紹了對(duì)于Python異常處理方法的建議,摘選自StackOverflow上的熱門問題的回答,闡述了except:pass的使用時(shí)需要注意的地方,需要的朋友可以參考下

翻譯自StackOverflow中一個(gè)關(guān)于Python異常處理的問答。

問題:為什么“except:pass”是一個(gè)不好的編程習(xí)慣?

我時(shí)常在StackOverflow上看到有人評(píng)論關(guān)于except: pass的使用,他們都提到這是一個(gè)不好的Python編程習(xí)慣,應(yīng)該避免??晌蚁胫罏槭裁??有時(shí)候我并不在意出現(xiàn)的錯(cuò)誤,而是只想讓我的程序繼續(xù)進(jìn)行下去。就像這樣:
 

try:
  something
except:
  pass

為什么這么使用except:pass不好?這背后的原因是什么,是不是因?yàn)檫@樣我會(huì)放掉一些本該被處理的錯(cuò)誤?還是這樣我會(huì)捕獲到所有類型的錯(cuò)誤?

最佳回答:

正如你所猜測(cè)的那樣,這么做的確有兩個(gè)不好的地方。首先,因?yàn)闆]有指定任何異常類型,所以會(huì)捕獲到任何類型的錯(cuò)誤。其次,捕獲到錯(cuò)誤之后只會(huì)簡(jiǎn)單地讓它通過而不是采取必要的處理措施。

我接下來的解釋或許會(huì)有點(diǎn)長(zhǎng),所以將重點(diǎn)總結(jié)如下:
1. 不要將任意類型的錯(cuò)誤作為捕獲對(duì)象。必須明確你想要捕獲的錯(cuò)誤類型,并且寫明只捕獲它們。
2. 不要試圖簡(jiǎn)單地敷衍錯(cuò)誤處理動(dòng)作。除非這么做是有目的的,但這通常都不太好。

那么接下來讓我們更深入一些:

不要將任意異常作為捕獲目標(biāo)

當(dāng)在代碼中的某個(gè)地方使用異常捕獲語句塊時(shí),你通常知道這個(gè)地方可能會(huì)拋出異常,并且你也知道這個(gè)地方可能會(huì)發(fā)生什么樣的問題進(jìn)而拋出何種異常,一旦異常被拋出,你將捕獲到這個(gè)異常并使程序回到正軌上來。這就意味著你一定對(duì)這種異常有所準(zhǔn)備,并能夠在它發(fā)生的時(shí)候及時(shí)采取措施進(jìn)行處理。

舉個(gè)例子,你需要用戶輸入一個(gè)數(shù)字,并且使用int()函數(shù)將用戶輸入的字符串轉(zhuǎn)換為整數(shù)類型,這時(shí)候你一定會(huì)想到如果輸入的字符串并不是數(shù)字,那么就會(huì)發(fā)生值錯(cuò)誤(ValueError)。如果真的發(fā)生了錯(cuò)誤,那么你可以通過簡(jiǎn)單的讓用戶重新輸入來讓程序回到正軌,所以捕獲值錯(cuò)誤以及促使用戶重新輸入就是一個(gè)比較合理的處理策略。再舉一個(gè)例子,如果你想從一個(gè)文件中讀取配置信息,但正巧這個(gè)文件不存在。那么因?yàn)檫@是一個(gè)配置文件,如果它不存在你會(huì)返回一些默認(rèn)的配置選項(xiàng),所以這個(gè)文件就不是這么必要了。在這個(gè)例子中,捕獲文件未找到錯(cuò)誤(FileNotFoundError)以及返回默認(rèn)配置項(xiàng)則是一個(gè)比較合適的處理策略。通過以上兩個(gè)例子可以看到,我們都是在等待捕獲特定的錯(cuò)誤,并且針對(duì)每種錯(cuò)誤都有特定的處理策略。

然而,如果我們?cè)谶@里捕獲所有的異常,那么為特定異常準(zhǔn)備的那些處理策略就會(huì)因?yàn)橛龅椒钦n愋偷漠惓6?,這將會(huì)使得正常的程序流程中斷并且無法恢復(fù)。

讓我們還是舉配置文件的那個(gè)例子。正常的處理策略是如果發(fā)現(xiàn)文件并不存在,我們將使用默認(rèn)的配置項(xiàng),并可能在稍后決定是否將當(dāng)前的配置項(xiàng)自動(dòng)保存為配置文件(這樣的話下一次文件就肯定存在了)?,F(xiàn)在讓我們假定我們捕獲到了一個(gè)IsADirectoryError或是PermissionError錯(cuò)誤,在這種情況下,我們可能不想讓程序繼續(xù)執(zhí)行,我們?nèi)匀荒軌蚴褂媚J(rèn)的配置參數(shù),但是隨后我們就不能保存文件了。也有可能用戶希望使用自定義的配置項(xiàng),所以這樣的話就不能使用默認(rèn)配置項(xiàng)了。所以我們這時(shí)候可能需要立即告知用戶并停止當(dāng)前程序。也有可能我們并不想在這么一小塊代碼中做這么多的事情,而是讓應(yīng)用層面的部分去關(guān)心它,所以我們也可能讓這個(gè)錯(cuò)誤浮到頂層,讓頂層的業(yè)務(wù)邏輯去處理。

Python 2 idioms document文檔中也提到了一個(gè)簡(jiǎn)單的例子:如果在我們的代碼中出現(xiàn)了一個(gè)簡(jiǎn)單的拼寫錯(cuò)誤而導(dǎo)致程序錯(cuò)誤。在這種情況下因?yàn)槲覀儾东@所有的異常,所以我們將會(huì)捕獲到名稱錯(cuò)誤(NameErrors)以及語法錯(cuò)誤(SyntaxErrors)。兩者都是常見的錯(cuò)誤,并且兩者都是不希望出現(xiàn)在我們最終代碼中的。但是因?yàn)槲覀兪裁串惓6即?,?dāng)異常發(fā)生時(shí)我們將無法區(qū)分具體的錯(cuò)誤類型并且無法進(jìn)行調(diào)試。

但是也存在這樣一些并未預(yù)先準(zhǔn)備的危險(xiǎn)異常,諸如系統(tǒng)錯(cuò)誤(SystemError)就很少發(fā)生以至于我們根本沒有準(zhǔn)備;這些異常通常需要更復(fù)雜的處理操作,這些操作通??赡軙?huì)要求我們停止當(dāng)前的工作。

在任何情況下,通過局部代碼實(shí)現(xiàn)對(duì)所有異常的處理基本上都是不可能的,所以你應(yīng)該有針對(duì)性的去處理那些經(jīng)過準(zhǔn)備的特定異常。有些人曾建議至少應(yīng)該明確指明基本異常(Exception)這樣的不包含諸如系統(tǒng)退出(SystemExit)和鍵盤中斷(KeyboardInterrupt)這樣設(shè)計(jì)用來終止應(yīng)用程序的異常。但是我想說這樣還是不夠明確,并且我個(gè)人認(rèn)為只有在一個(gè)地方才能僅僅只捕獲Exception或是任何類型的異常,那就是一個(gè)單獨(dú)的,應(yīng)用程序?qū)用娴漠惓2东@器,并且這個(gè)捕獲器唯一的任務(wù)就是去捕獲任何可能出現(xiàn)的未經(jīng)準(zhǔn)備的漏網(wǎng)異常。這樣的話我們?nèi)匀荒軌虮A粢馔獍l(fā)生異常的相關(guān)信息作為進(jìn)一步的代碼擴(kuò)展的依據(jù)(讓然如果我們能讓程序恢復(fù)的話),這樣下一次我們就能夠把這個(gè)異常在合適的地方顯式地指定出來或是指導(dǎo)我們撰寫測(cè)試用例以保證錯(cuò)誤不再發(fā)生(當(dāng)然了,這一切還是要當(dāng)我們對(duì)特定異常有所準(zhǔn)備時(shí),沒有準(zhǔn)備的異常還是會(huì)溜掉)。

在異常處理的邏輯中,不要什么都不做

當(dāng)顯式地捕獲到有限的幾個(gè)異常之后,很多時(shí)候我們的確不需要做什么特別的處理。這種情況下,except SomeSpecificException: pass這么做是可以的。但是大多數(shù)情況下,我們還是需要一些與錯(cuò)誤恢復(fù)相關(guān)的代碼,例如重復(fù)嘗試的動(dòng)作以及設(shè)置默認(rèn)值。

同時(shí)也考慮到其它情況,例如如果我們的代碼結(jié)構(gòu)已經(jīng)確定了必須不斷嘗試直到成功才能繼續(xù),那么什么也不做就已經(jīng)夠了。具體來說,我們需要用戶輸入一個(gè)數(shù)字,因?yàn)槲覀冎烙脩艨赡懿粫?huì)按照我們?cè)O(shè)計(jì)的那樣做,所以我們會(huì)將這個(gè)部分放入一個(gè)循環(huán),比如像這樣:
 

def askForNumber ():
  while True:
    try:
      return int(input('Please enter a number: '))
    except ValueError:
      pass

因?yàn)槲覀儠?huì)不斷讓用戶輸入直到?jīng)]有異常拋出為止,這種情況下我們就不需要在except塊中做其他任何特別的操作,這樣就夠了。當(dāng)然了,有人會(huì)說你至少應(yīng)該讓用戶得到一些錯(cuò)誤信息以明確他們?yōu)槭裁丛诖吮环磸?fù)地要求輸入。

在其他一些情況下,except塊中的passing語句顯示了我們并沒有真正的對(duì)異常做好準(zhǔn)備。除非是一些簡(jiǎn)單的異常(諸如值錯(cuò)誤ValueError或類型錯(cuò)誤TypeError)我們都應(yīng)該做一些操作,原因也很明顯,避免簡(jiǎn)單的passing。如果真沒什么可做的(如果你真的確定),那么考慮加一些解釋性的注釋在此;否則,請(qǐng)擴(kuò)展except塊添加一些恢復(fù)性的代碼。

except: pass

最不能容忍的就是兩者的結(jié)合了。這意味著我們自愿捕獲任何異常(包括那些我們沒有準(zhǔn)備的)并且對(duì)它們視而不見。你應(yīng)該至少在日志中記錄一下這個(gè)錯(cuò)誤并且向上提出來終止當(dāng)前程序(我就不信出現(xiàn)MemoryError你的程序依然能正常運(yùn)行)。放過這些異常將會(huì)使程序在錯(cuò)誤的軌道上繼續(xù)運(yùn)行下去并且丟掉了關(guān)鍵的錯(cuò)誤信息從而使得錯(cuò)誤不易被發(fā)現(xiàn),特別是當(dāng)不是你親自遇到它的時(shí)候。

所以,底線是去捕獲那些經(jīng)過準(zhǔn)備的特定異常;其他發(fā)生的異常要么是等著你去修復(fù)的錯(cuò)誤,要么是你無法處理的。當(dāng)真的沒有什么可做的時(shí)候放過某些特定異常是可以的,其他情況如果這么做就只能被認(rèn)為是怠工或偷懶了。你的確應(yīng)該去處理這些異常的。

相關(guān)文章

最新評(píng)論