1. 程式人生 > 程式設計 >詳解python中的異常捕獲

詳解python中的異常捕獲

異常

異常是程式發生錯誤的訊號,程式一旦出錯就會丟擲異常,程式的執行隨之終止。

# 異常處理的三個特徵
- 異常的追蹤資訊
- 異常的型別
- 異常的內容

捕獲異常的目的:為了增強程式的健壯性,即便程式執行過程中出錯,也不要終止程式,而是捕獲異常並處理,將出錯資訊記錄到日誌內。

# 語法上錯誤SyntaxError
- 處理方式1:必須在程式執行前就改正

# 邏輯上的錯誤
- 錯誤發生的條件是可以預知的 --> if判斷
- 錯誤發生的條件是無法預知的 --> 異常捕獲 try

本來程式一旦出現異常就整體結束掉了,有了異常處理以後,在被檢測的程式碼塊出現異常時,被檢測的程式碼塊中異常發生位置之後的程式碼將不會執行,取而代之的是執行匹配異常的except子程式碼塊,其餘程式碼均正常執行。

異常捕獲

當被檢測的程式碼塊中有可能觸發不同型別的異常時,針對不同型別的異常:

如果我們想分別用不同的邏輯處理,需要用到多分支的except(類似於多分支的elif,從上到下依次匹配,匹配成功一次便不再匹配其他)

try:
  # 有可能會丟擲異常的程式碼
  子程式碼1
  子程式碼2
  子程式碼3
except 異常型別1 as e:	# as語法將異常型別的值賦值給變數e,這樣我們通過列印e便可以知道錯誤的原因
  pass
except 異常型別2 as e:
  pass
...
else:
  如果被檢測的子程式碼塊沒有異常發生,則會執行else的子程式碼
finally:
  無論被檢測的子程式碼塊有無異常發生,都會執行finally的子程式碼

  
# try不能和else單獨連用
# try 和 finally 連用,就算出了異常也先執行finally下程式碼塊再丟擲異常

如果我們想多種型別的異常統一用一種邏輯處理,可以將多個異常放到一個元組內,用一個except匹配。

try:
  被檢測的程式碼塊
except (NameError,IndexError,TypeError):
  觸發NameError或IndexError或TypeError時對應的處理邏輯

如果我們想捕獲所有異常並用一種邏輯處理,Python提供了一個萬能異常型別 Exception

try:
  被檢測的程式碼塊
except NameError:
  觸發NameError時對應的處理邏輯
except IndexError:
  觸發IndexError時對應的處理邏輯
except Exception:
  其他型別的異常統一用此處的邏輯處理

在不符合Python直譯器的語法或邏輯規則時,是由Python直譯器主動觸發的各種型別的異常,而對於違反程式設計師自定製的各類規則,則需要由程式設計師自己來明確地觸發異常,這就用到了raise語句,raise後必須是一個異常的類或者是異常的例項

class Student:
  def __init__(self,name,age):
    if not isinstance(name,str):
      raise TypeError('name must be str')
    if not isinstance(age,int):
      raise TypeError('age must be int')

    self.name=name
    self.age=age

stu1=Student(4573,18) # TypeError: name must be str
stu2=Student('egon','18') # TypeError: age must be int

在內建異常不夠用的情況下,我們可以通過繼承內建的異常類來自定義異常類

class PoolEmptyError(Exception): # 可以通過繼承Exception來定義一個全新的異常
  def __init__(self,value='The proxy source is exhausted'): # 可以定製初始化方法
    super(PoolEmptyError,self).__init__()
    self.value=value

  def __str__(self): # 可以定義該方法用來定製觸發異常時列印異常值的格式
    return '< %s >' %self.value


class NetworkIOError(IOError): # 也可以在特定異常的基礎上擴充套件一個相關的異常
  pass


raise PoolEmptyError # __main__.PoolEmptyError: < The proxy source is exhausted >
raise NetworkIOError('連線被拒絕') # __main__.NetworkIOError: 連線被拒絕

最後,Python還提供了一個斷言語句assert expression,斷定表示式expression成立,否則觸發異常AssertionError,與raise-if-not的語義相同,如下

age='18'

# 若表示式isinstance(age,int)返回值為False則觸發異常AssertionError
assert isinstance(age,int)

# 等同於
if not isinstance(age,int):
  raise AssertionError

在瞭解了異常處理機制後,本著提高程式容錯性和可靠性的目的,讀者可能會錯誤地認為應該儘可能多地為程式加上try...except...,這其是在過度消費程式的可讀性,因為try...except本來就是你附加給程式的一種額外的邏輯,與你的主要工作是沒有多大關係的。所以不要隨便使用異常捕獲,只用噹噹異常發生時不可預知時,或萬不得已時才使用異常捕獲。

以上就是詳解python中的異常捕獲的詳細內容,更多關於python 異常捕獲的資料請關注我們其它相關文章!