到目前為止,我們對錯誤和異常講的并不多,但至少肯定有兩種大家見過了:syntax errors和exceptions。
 解析程序返回了錯誤的行數,并且用箭頭指出了最早發現錯誤的位置。當然后面也許還有錯誤,這個箭頭是告訴我們錯誤至少在箭頭前已經發生了,在這個例子中錯誤發生在PRint()函數之前,在這之前缺少一個冒號。最先返回的是錯誤的文件名,這可以方便我們知道是哪個腳本里的錯誤,要不自己找起來就太痛苦了。
解析程序返回了錯誤的行數,并且用箭頭指出了最早發現錯誤的位置。當然后面也許還有錯誤,這個箭頭是告訴我們錯誤至少在箭頭前已經發生了,在這個例子中錯誤發生在PRint()函數之前,在這之前缺少一個冒號。最先返回的是錯誤的文件名,這可以方便我們知道是哪個腳本里的錯誤,要不自己找起來就太痛苦了。 錯誤信息的最后一行會提示發生了些什么,異常有很多種類型,消息中也會顯示異常的類型,在例子中我們看到了3中異常:ZeroDivisionError、NameError、TypeError。一般來說還是顧名思義都能清楚的明白發生了些啥。上面看到的這些異常類型都是內建的異常,這些內建的異常都會把異常類型打印出來,但是用戶自建的可能會有所區別(當然自建的異常也是非常重要的)。省下的部分會提示更多的異常細節和引起異常的原因,錯誤信息前面的部分使用trackback(這是一個日志工具很有用的)顯示錯誤異常發生的位置。在標準庫的bltin-exception中有對內建異常的詳細介紹。
錯誤信息的最后一行會提示發生了些什么,異常有很多種類型,消息中也會顯示異常的類型,在例子中我們看到了3中異常:ZeroDivisionError、NameError、TypeError。一般來說還是顧名思義都能清楚的明白發生了些啥。上面看到的這些異常類型都是內建的異常,這些內建的異常都會把異常類型打印出來,但是用戶自建的可能會有所區別(當然自建的異常也是非常重要的)。省下的部分會提示更多的異常細節和引起異常的原因,錯誤信息前面的部分使用trackback(這是一個日志工具很有用的)顯示錯誤異常發生的位置。在標準庫的bltin-exception中有對內建異常的詳細介紹。 這個水印的效果真心不太好,以后就不用水印了,try協議是這么工作的:首先執行try的語句,就是try和except之間這部分。如果沒有異常的話,except部分就會被跳過,try的語句會被執行完。如果在執行try語句部分時發生了異常,那么try語句省下的部分都不會被執行,而是直接跳轉到except部分。如果發生的異常能和關鍵字匹配,那么就執行對應的操作。如果沒能在except中找到對應的異常關鍵字,他會到上一級中尋找,如果還是找不到的話執行就會終止并提示unhandled exception。一個try協議可以擁有多個異常處理語句,但是最多只會執行一個,因為不能同時出現兩個異常。但是一個except語句可以用元組的包含多個異常,就是說自己個異常的處理方式是一樣的:... except (RuntimeError, TypeError, NameError):... pass在選擇異常處理時,遵循的是基類優先,就是說子類可以對應上基類的異常處理。這么說好亂啊,我們還是直接看例子吧:
這個水印的效果真心不太好,以后就不用水印了,try協議是這么工作的:首先執行try的語句,就是try和except之間這部分。如果沒有異常的話,except部分就會被跳過,try的語句會被執行完。如果在執行try語句部分時發生了異常,那么try語句省下的部分都不會被執行,而是直接跳轉到except部分。如果發生的異常能和關鍵字匹配,那么就執行對應的操作。如果沒能在except中找到對應的異常關鍵字,他會到上一級中尋找,如果還是找不到的話執行就會終止并提示unhandled exception。一個try協議可以擁有多個異常處理語句,但是最多只會執行一個,因為不能同時出現兩個異常。但是一個except語句可以用元組的包含多個異常,就是說自己個異常的處理方式是一樣的:... except (RuntimeError, TypeError, NameError):... pass在選擇異常處理時,遵循的是基類優先,就是說子類可以對應上基類的異常處理。這么說好亂啊,我們還是直接看例子吧: 在這個例子中,會打出B,B,B因為C和D都會直接對應上基類B的異常處理,想要打印出B,C,D的話可以將except反序的寫,就是先寫D的處理,再寫C的處理,最后寫B的處理。最后一個except語句其實是可以省略異常的關鍵字的,這是他就成了通配符,但是這種用法需要十二分的小心,因為她可能會把真正的錯誤隱藏掉。當然他也是可以打印錯誤信息的,還可以重新引起其他異常:
在這個例子中,會打出B,B,B因為C和D都會直接對應上基類B的異常處理,想要打印出B,C,D的話可以將except反序的寫,就是先寫D的處理,再寫C的處理,最后寫B的處理。最后一個except語句其實是可以省略異常的關鍵字的,這是他就成了通配符,但是這種用法需要十二分的小心,因為她可能會把真正的錯誤隱藏掉。當然他也是可以打印錯誤信息的,還可以重新引起其他異常: try...except協議還有另外一個else選項,他必須寫在except之后,如果try沒有引起異常那么就執行else內代碼:
try...except協議還有另外一個else選項,他必須寫在except之后,如果try沒有引起異常那么就執行else內代碼: 這樣執行代碼的好處是可以避免發生了其他的異常影響語句的執行。當一個異常發生的時候,它可能還有幾個伴隨這個異常的變量。這些變量的類型和表現都是取決于異常的類型的,except可以將變量指定給異常實例。這些變量會被保存在異常實例的instance.args中。異常實例定義了__str__()所以這些變量都可以很方便的被打印出來,我們可以在try語句中直接將變量指定給異常實例:
這樣執行代碼的好處是可以避免發生了其他的異常影響語句的執行。當一個異常發生的時候,它可能還有幾個伴隨這個異常的變量。這些變量的類型和表現都是取決于異常的類型的,except可以將變量指定給異常實例。這些變量會被保存在異常實例的instance.args中。異常實例定義了__str__()所以這些變量都可以很方便的被打印出來,我們可以在try語句中直接將變量指定給異常實例:
 異常處理并不僅僅局限于try語句的代碼中,在其中調用其他部分如果引起對應的異常也會轉到except中:
異常處理并不僅僅局限于try語句的代碼中,在其中調用其他部分如果引起對應的異常也會轉到except中:

 注意raise只能引起它指定的那一個異常,不能同時引起多個。且引起的要么是異常實例,要么是異常類。如果傳入一個類,他會直接調用構造器構造一個沒有任何參數的實例,如果你想要引起一個異常但是還不打算解決它,那么可以在except中再次raise這個異常:
注意raise只能引起它指定的那一個異常,不能同時引起多個。且引起的要么是異常實例,要么是異常類。如果傳入一個類,他會直接調用構造器構造一個沒有任何參數的實例,如果你想要引起一個異常但是還不打算解決它,那么可以在except中再次raise這個異常:

我們先定義一個基類,然后用子類解決具體的問題。在命名規則上我們一般保證異常類都是以Error來結尾的。許多標準模塊都會定義異常類來解決自己模塊定義方法中出現的錯誤,我們會在class章節中看到更多的內容。
8.6 Defining Clean-up Actionstry協議還有另一個可選項叫做finally,顧名思義他是在最后執行的,而且也是必須執行的~無論是否引起的異常: 在結束try協議之前finally部分是一定會被執行的,無論是否發生了異常。如果在try語句中發生了異常,但是except中沒有對應的關鍵字,那么這個異常將會被暫時忽略,在執行完finally的代碼后在提起這個異常,我們看一個稍微復雜點的例子:
在結束try協議之前finally部分是一定會被執行的,無論是否發生了異常。如果在try語句中發生了異常,但是except中沒有對應的關鍵字,那么這個異常將會被暫時忽略,在執行完finally的代碼后在提起這個異常,我們看一個稍微復雜點的例子: 可以清楚的看到,finally部分的代碼肯定是會執行的。TypeError的異常不在except中,所以他是在finally代碼執行完了之后才被提起的。在實際編碼工作中,finally部分主要是用來釋放外部資源的,無論它是否成功的被執行了。
可以清楚的看到,finally部分的代碼肯定是會執行的。TypeError的異常不在except中,所以他是在finally代碼執行完了之后才被提起的。在實際編碼工作中,finally部分主要是用來釋放外部資源的,無論它是否成功的被執行了。 這段代碼在執行之后,workfile并沒用被關閉,他會一直保存在內存器(記憶體)中,在一個簡單的腳本中這沒有什么問題,但是在一個大型的應用中這可能就會變得嚴重。使用with結構可以很好的解決這個問題:
這段代碼在執行之后,workfile并沒用被關閉,他會一直保存在內存器(記憶體)中,在一個簡單的腳本中這沒有什么問題,但是在一個大型的應用中這可能就會變得嚴重。使用with結構可以很好的解決這個問題: 這段代碼執行結束后,即使發生了異常,文件f也一定是被關閉的。包含有這樣功能的對象都會在他們的說明中明確的指出。
這段代碼執行結束后,即使發生了異常,文件f也一定是被關閉的。包含有這樣功能的對象都會在他們的說明中明確的指出。新聞熱點
疑難解答