Python 2.7 錯誤與異常
1 語法錯誤
產生語法錯誤時,解析器會重複錯誤的行,並且使用一個箭頭指向錯誤行中最早發現錯誤的位置。錯誤便是由箭頭之前的符號引發的(至少是在此處檢測到的)。檔名與行數將會被打印出來,當輸入來自指令碼時用以得知在哪裡找尋錯誤。
2 異常
在執行期間檢測到的錯誤稱之為異常,它們通常不會無條件失敗。 大多數異常並不是由程式處理並輸出錯誤資訊,這些異常稱為內建異常,例如,除零引發的ZeroDivisionError。
異常有著不同的型別,異常型別將會作為異常資訊的一部分輸出。 作為異常型別列印的字串實際上是被引發的內建異常的名稱。 這一點對於所有的內建異常都適用,但是對於使用者自定義的異常並不是一定可行(即使這是非常有用的慣例)。 標準異常名稱是內建識別符號,並不是保留關鍵字。
錯誤資訊的剩餘部分是每個錯誤型別以及造成的原因的詳盡描述。
錯誤資訊的前一部分以堆疊形式顯示了異常發生的上下文。它通常包括列出堆疊回溯的源行數,但是,它不會顯式從標準輸入讀取的行數。
3 處理異常
while True:
try:
x = int(raw_input("Enter a number: "))
break
except ValueError:
print "Try again..."
note:在輸入整數型別的值之前,不斷提示輸入。
try語句處理過程:
- 首先,try子句(try與except關鍵字之間的語句)將會執行。
- 如果沒有異常發生,except子句將會被跳過並且辦成try語句的執行。
- 如果在執行try子句的過程中發生了異常,try子句的剩餘部分將會被跳過。接著,如果異常型別匹配except關鍵字之後的異常名,except子句將被執行,然後執行try子句之後的語句。
- 如果一個異常發生,但是except之後的異常名稱沒有匹配發生的異常,該異常將會被傳遞給外層try語句,如果始終沒有找到異常的處理程式,執行將會被終止,輸出錯誤資訊。
一個try語句可以有多個except子句,用來指定不同型別異常的處理程式。至多隻有一個處理程式被執行。 處理程式只會處理髮生在對應try語句中的異常,不會處理同一try語句的其他對應處理程式中發生的異常。
# except子句可以使用由多個異常組成的元組
try :
pass
except (RuntimeError, TypeError, NameError):
pass
import sys
try:
f = open('ttt')
s = f.readline()
i = int(s.strip())
print i
except IOError as e:
print e.args
print e.errno, e.strerror
except ValueError:
print 'convert failure'
except:
print 'Unexcepted error:', sys.exc_info()[0]
raise
else:
print "success"
note:except不帶異常,會捕獲所有的異常。 note:else子句將會在try子句不丟擲異常的情況下執行。 note:except xxx as xx:用於為異常指定繫結的變數,異常例項的引數儲存在異常的args屬性中。
如果異常有引數,引數將會作為未處理的異常的最後一部分資訊打印出來。
# 處理try呼叫的函式引發的異常
def this_falis():
x = 1/0
try:
this_falis()
except ZeroDivisionError as detail:
print detail
4 提出異常
# 手動提出異常
raise NameError("sdfs")
# except再丟擲異常
try:
raise NameError('aaaa')
except NameError:
print "except"
raise
5 使用者自定義異常
# 定義異常MyError,使用value屬性替換args屬性
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
當建立一個可能提出多個不同異常的模組時,常見的操作是在模組中建立建一個異常基類,然後針對不同的錯誤狀況建立特定的異常子類。 大多數的異常一般以“Error”為結尾命名,類似標準異常的命名。 許多標準模組定義了自己的異常,用於輸出在自己定義的函式中可能發生的錯誤。
6 定義清理行為
使用finally子句定義清理行為,無論在什麼情況下,清理行為都必須執行。
# 定義清理行為
try:
raise KeyboardInterrupt
finally:
print '!!!!'
在離開try語句之前,無論異常是否發生,finally子句總會執行。當try子句中產生了異常並且此異常沒有對應的except子句(或是異常產生於except或else子句中),在finally子句執行之後,此異常才會被再丟擲。當try子句中的語句通過break、continue或return語句離開了try子句,此時finally子句會在離開程式的位置執行。
實際應用程式中,finally一般用於釋放外部資源(例如檔案或網路連線),這樣無論資源的使用是否正常執行,都可以完成資源釋放。
7 預定義清理行為
一些物件定義了不需要此物件時的標準清理行為,無論使用物件的操作是否執行成功。
with open("sss") as f:
for line in f:
print line