Python 對異常與錯誤的處理策略,用 try...except,還是 if...else...,哪種比較好?

Beginning Python From Novice to Professional, 2nd Edition, CHAPTER 8, EXCEPTIONS, Page 173:

正文中這樣描寫:

The point is that using try/except statements is in many cases much more natural (more 「Pythonic」) than if/else, and you should get into the habit of using them where you can.1

注釋:

1. The preference for try/except in Python is often explained through Rear Admiral Grace Hopper』s words of wisdom, 「It』s easier to ask forgiveness than permission.」 This strategy of simply trying to do something and dealing with any errors, rather than doing a lot of checking up front, is called the Leap Before You Look idiom.

————————————————————————————————

Python 基礎教程(第2版),第8章,異常,第136頁:

在很多情況下,使用try/except語句比使用if/else會更自然一些(更「Python化」),應該養成儘可能使用if/else語句的習慣。 ①

①try/except語句在 Python 中的表現可以用海軍少將Grace Hopper的妙語解釋:「請求寬恕易於請求許可。」在做一件事時去處理可能出現的錯誤,而不是在開始做事前就進行大量的檢查,這個策略可以總結為習語「看前就跳(Leap Before You Look)」。

—————————————————————————————————

我對前面英文的理解是要讓讀者多用 try/except,而中文的翻譯是說多用 if/else,是我理解錯了,還是翻譯的有錯誤?


Dustin Getz"s blog

用monad最好。


沒有最好的方式。

如果命中的可能性比較大,那就用 try...except...,反之用 if...else...,原因是盡量減少索引檢查和生成異常。


本文講的碼農版Python技巧的確是鼓勵用try,大致上你的代碼應該是一個try block,下面跟著一串except處理各種異常,而不是每一個語句外面套一個if。

要高端的請參見monad……


你理解的沒錯,翻譯有錯誤。

但此書英文版作者對if-else和try-except的理解,個人覺得並不是正確的。

方式的存在必然有其應用的場景,不要手裡有了鎚子就看什麼都是釘子。

簡單來講,作為使用者,應該按照所使用庫的習慣來決定用那種方式處理錯誤,如果庫使用throw則try,如果庫使用return則if。

而自己的模塊,根據開發時間和模塊的重要性的不同而選擇不同模式。

如,開發時間短,腳本為臨時性的則try-except;如代碼比較關鍵要求穩定,如出錯c需要詳細的錯誤提示則if-else。

所以,正確的習慣不是去習慣有某一個,而是應該具體問題具體分析根據具體場景選擇問題的解決方式。


轉帖,希望有幫助:

Python黑帽編程2.7 異常處理

https://www.zhihu.com/people/xuan-hun

玄魂工作室-玄魂 · 12 小時前

Python黑帽編程2.7 異常處理

異常是個很寬泛的概念,如果程序沒有按預想的執行,都可以說是異常了。遇到一些特殊情況沒處理會引發異常,比如讀文件的時候文件不存在,網路連接超時。程序本身的錯誤也可以算作異常,比如把字元串當整數來處理,拼寫錯誤。

不論是系統還是框架,都會對基本異常進行分類,比如IO異常,內存溢出等等。很多時候,針對特有的業務,我們也可以自定異常。

下面我們先看一個引發異常的例子:

Print "hello"

這個例子很簡單,我們將print的首字母大寫。這會引發一個錯誤:

圖2

我們可以觀察到有一個SyntaxError被引發,並且檢測到的錯誤位置也被列印了出來。捕獲錯誤,列印錯誤信息,這本身就是一種異常處理。那麼我們如何在代碼中處理異常呢?

2.7.1 TRY ….EXCEPT

例如我們用如下代碼去打開文件:

open("abc.txt","r")

但是要打開的文件並不存在,這個時候程序就會拋出異常,如下圖所示:

圖3

我們看到拋出的錯誤為 IOError,那麼我們可以使用如下的代碼來處理這個異常。

try:
open("abc.txt","r")
except IOError,msg:
print msg

運行結果如下:

圖4

我們把所有可能引發錯誤的語句放在try塊中,然後在except從句中處理所有的錯誤和異常。except從句可以專門處理單一的錯誤或異常,或者一組包括在圓括弧內的錯誤/異常。如果沒有給出錯誤或異常的名稱,它會處理 所有的 錯誤和異常。對於每個try從句,至少都有一個相關聯的except從句。

例如:

try:
open("abc.txt","r")
except IOError,msg:
print msg
except:
print "other erro"

如果某個錯誤或異常沒有被處理,默認的Python處理器就會被調用。它會終止程序的運行,並且列印一個消息,我們已經看到了這樣的處理。

2.7.2 拋出異常

我們可以使用raise語句 引發 異常。你還得指明錯誤/異常的名稱和伴隨異常 觸發的 異常對象。我們可以引發的錯誤或異常應該分別是一個Error或Exception類的直接或間接導出類。

我們先看示例代碼:

#!/usr/bin/python

class ShortInputException(Exception):
"""A user-defined exception class."""
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast

try:
s = raw_input("Enter something --&> ")
if len(s) &< 3: raise ShortInputException(len(s), 3) # Other work can continue as usual here except EOFError: print " Why did you do an EOF on me?" except ShortInputException, x: print "ShortInputException: The input was of length %d, was expecting at least %d" % (x.length, x.atleast) else: print "No exception was raised."

這段代碼中我們首先自定義了一個ShortInputException類,它繼承自Exception類,構造函數接受兩個參數輸入字元串的長度和最小長度。接下來代碼中,我們獲取用戶輸入,判斷長度是否小於3,如果小於3觸發ShortInputException。我們從終端啟動這個腳本,運行結果如下:

圖5

2.7.3 TRY..FINALLY

當我們需要不管是否有異常,都要執行某段代碼的時候,就需要finally出場了。看下面的示例:

def test1():
try:
print("to do stuff")
raise Exception("hehe")
print("to return in try")
return "try"
except Exception:
print("process except")
print("to return in except")
return "except"
finally:
print("to return in finally")
return "finally"

test1Return = test1()
print("test1Return : " + test1Return)

在 try 中 raise一個異常,就立刻轉入 except 中執行,在except 中遇到 return 時,就強制轉到 finally 中執行, 在 finally 中遇到 return 時就返回。運行結果如下:

圖6

2.7.9 小結

本節我們學習了Python中基本的異常處理,和自定義異常的方法。

下一節我們學習套接字編程。

第2.7節《套接字編程》已經在微信訂閱號搶先發布,心急的同學進入訂閱號(二維碼在下方),從菜單「網路安全」—&>」Python黑帽編程」進入即可。

完整系列教程,請關注我的微信訂閱號(xuanhun521,下方二維碼),我會第一時間在訂閱號推送圖文教程和視頻教程。內有驚喜。問題討論請加qq群:Hacking (1群):303242737 Hacking (2群):147098303。

點擊打開二維碼


我也同意用monad,但是python那個lambda配合他的縮進實在是太丑了。


題主買到盜版了~ 上個月看的,印象還挺深的,我記得書中明明是try/except .明天回學校,書都已經放包里了,睡覺之前刷刷知乎,看到這問題,翻出來看了看,嗯,我沒記錯,題主應該是買到盜版了。╮(╯▽╰)╭

再說下我的一些個人看書心得吧,看這種技術書,總會碰到一些暫時沒有理解的句子,這時不要總是作死的揪著她們不放,重點是看這句話的目的是什麼(比如闡述一種編程概念或技巧),這個目的通常就是句子所處段落的小標題了,所以先把那句話放一邊,接著往下看,也許就把目的弄明白了。

同一件事情,不同的人因為各自不同的經歷和環境就會有不同的描述方法,作者寫書是為了傳播與分享某種技術,大多數作者不是技術的創造者,我們看書的目的是要掌握這種技術,能利用這種技術用於生產實踐,而不需要對作者闡述這種技術的語句給理解的不差毫釐。就比如你弄懂一項技術時,你在像他人講解這門技術時,就必定會帶有你自己的個人風格特點了。 碎覺鳥,明早6點多就得起床趕班車克市裡坐火車回校,回校再從書中找幾個例子~

PS:用手機碼的,發布時總出現圖片正在上傳中,請稍後。。。醉了

===========================================

1月9號更新:用pc上傳了書的封面及舉例,還有簡單分了下段落。

比如我在看到第九章的八皇后問題時(當時我並不明白八皇后的意思),如果按我以前的做法,我會先搜索一下八皇后的概念後才來看,但是並沒有那個必要,因為作者舉八皇后的目的是為了讓我們掌握如何用生成器解決複雜的遞歸問題,而不是了解八皇后這個概念,而且我們在接下來的代碼閱讀理解中,自然而然就明白了八皇后的概念,這樣就不用分心搜索而導致沒必要的時間浪費了。


try except


我覺得try except足夠,既可以快速查錯,方便定位,也可以避免由於未知錯誤造成的癱瘓。


兩種情況:

1.未知的異常用try...except.

2.可預見的可以用if..else..處理下。

----------

python的異常處理沒java的強大。


我比較喜歡scala的錯誤處理機制。沒有if else 沒有try catch 沒有NullException。

Scala提供了Option機制來解決,代碼中不斷檢查null的問題。再見 NullException

這個例子包裝了getProperty方法,使其返回一個Option。 這樣就可以不再漫無目的地null檢查。只要Option類型的值即可。

使用pattern match來檢查是常見做法。也可以使用getOrElse來提供當為None時的默認值。

給力的是Option還可以看作是最大長度為1的List,List的強大功能都可以使用。

def getProperty(name: String): Option[String] = {

val value = System.getProperty(name)

if (value != null) Some(value) else None

}

val osName = getProperty("os.name")

osName match {

case Some(value) =&> println(value)

case _ =&> println("none")

}

println(osName.getOrElse("none"))

osName.foreach(print _)

輸出結果:

linux

linux

linux

參考地址:Scala Tour


推薦閱讀:

python numpy 數組如何對每個元素進行操作?
python 中如何實現一行輸入多個值 ?
為什麼看不懂廖雪峰的Python學習教程?
Python中 pickle有什麼意義,pickle了再恢復?
在Python中如何修改字元串中的某一位字元?

TAG:Python | 編程 | Python入門 | 異常處理 |