內容簡述:
- 1、異常
- 2、斷言
1、異常
瞭解異常前,首先是區分「語法錯誤」與「執行時異常」,語法錯誤是連編譯器都過不了的錯誤,比如if語句後面漏掉了冒號(:),程式跑都跑不起來;執行錯誤則是程式跑起來後,因為程式的業務邏輯問題引起的程式崩潰,比如除以0。
① Python中的常見異常
Exception類
因為是 所有異常類的父類
,又稱 萬能異常
,可以捕獲任何異常!Python中常見的異常如下表所示:
異常 | 描述資訊 |
---|---|
AssertionError | 斷言語句失敗 |
AttributeError | 嘗試訪問未知的物件屬性 |
IndexError | 索引超出序列的範圍 |
keyError | 字典中查詢一個不存在的Key |
NameError | 嘗試訪問一個不存在的變數 |
OSError | 作業系統產生的異常,比如FileNotFoundError |
SyntaxError | Python語法錯誤 |
TypeError | 不同型別間的無效操作 |
ZeroDivisionError | 除數為0 |
IOError | 輸入輸出錯誤 |
ValueError | 函式傳參型別錯誤 |
② 異常捕獲
Python中為我們提供了兩組語句用於異常捕獲,try-expect-else
和try-finally
。下面講解下六種常見的玩法:
「1. try捕獲了任何異常,直接丟給except後的程式碼塊處理」,程式碼示例如下:
try:
result = 1 / 0
except:
print("捕獲到異常了!")
複製程式碼
執行結果如下:
捕獲到異常了!
複製程式碼
「2. 捕獲特定型別」,程式碼示例如下:
try:
result = 1 / 0
except ZeroDivisionError:
print("捕獲到除數為零的錯誤")
複製程式碼
執行結果如下:
捕獲到除數為零的錯誤
複製程式碼
「3. 針對不同的異常設定多個except」,程式碼示例如下
執行結果如下:
try:
sum = 1 + '2'
result = 1 / 0
except TypeError as reason:
print("型別出錯:" + str(reason))
except ZeroDivisionError as reason:
print("除數為0:" + str(reason))
複製程式碼
執行結果如下:
型別出錯:unsupported operand type(s) for +: 'int' and 'str'
複製程式碼
「4. 對多個異常統一處理」,程式碼示例如下:
try:
result = 1 / 0
sum = 1 + '2'
except (TypeError, ZeroDivisionError) as reason:
print(str(reason))
複製程式碼
執行結果如下:
division by zero
複製程式碼
「5. 當沒有檢測到異常時才執行的程式碼塊,可以用else」,程式碼示例如下:
try:
result = 4 / 2
except ZeroDivisionError as reason:
print(str(reason))
else:
print("沒有發生異常,輸出結果:%d" % result)
複製程式碼
執行結果如下:
沒有發生異常,輸出結果:2
複製程式碼
「6. 無論是否發生異常都會執行的一段程式碼塊」,程式碼示例如下:
try:
result = 4 / 2
except ZeroDivisionError as reason:
print(str(reason))
else:
print("沒有發生異常,輸出結果:%d" % result)
finally:
print("無論是否發生異常都會執行~")
複製程式碼
執行結果如下:
沒有發生異常,輸出結果:2
無論是否發生異常都會執行。
複製程式碼
③ 異常丟擲
Python為我們提供的都是異常都是在特定條件下才會觸發的。而在一些特定的場景,某些操作可能會引起我們的業務異常,比如讓使用者輸入一串手機號碼,手機號碼由一串0-9的數字構成,而如果使用者輸入了其他字元,顯然是不合理的。我們可以通過正則對輸入的手機號碼進行校驗,如果是手機號碼就列印出來,不是的話則利用Python提供的raise關鍵字
丟擲一個ValueError異常。程式碼示例如下:
import re
# 注:這段正則你只需要知道是用來匹配電話號碼的,正則在爬蟲那裡會詳細講解
phone_compile =re.compile(r'^(0|86|17951)?(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])[0-9]{8}$')
number = input("請輸入一串手機號碼:")
if phone_compile.match(number) is not None:
print("您輸入的手機號碼是:%s" % number)
else:
raise ValueError
複製程式碼
執行結果如下:
請輸入一串手機號碼:123456787
Traceback (most recent call last):
File "F:/Project/Python/Book/Chapter 7/7_1_7.py", line 12, in <module>
raise ValueError
ValueError
複製程式碼
④ 自定義異常
上面通過raise關鍵字顯式的丟擲了一個內建的ValueError異常。如果程式裡除了這個號碼驗證還有郵箱驗證,我們又丟擲一個這樣的異常的話,會不利於異常的定位,異常是哪個地方引起的?對此,我們可以自定義異常,根據不同的錯誤丟擲對應的異常。我們自定義一個非手機號碼異常,程式碼示例如下:
# 自定義異常
class PhoneNumberException(Exception):
def __init__(self, message):
Exception.__init__(self)
self.message = message
if __name__ == '__main__':
phone_compile = re.compile(r'^(0|86|17951)?(13[0-9]|14[579]|15[0-35-9]|17[01678]|18[0-9])[0-9]{8}$')
number = input("請輸入一串手機號碼:")
if phone_compile.match(number) is not None:
print("您輸入的手機號碼是:%s" % number)
else:
raise PhoneNumberException("非法的手機號碼!")
複製程式碼
執行結果如下:
請輸入一串手機號碼:1234
Traceback (most recent call last):
File "F:/Project/Python/Book/Chapter 7/7_1_8.py", line 19, in <module>
raise PhoneNumberException("非法的手機號碼!")
__main__.PhoneNumberException
複製程式碼
⑤ sys.exc_info()函式
除了前面介紹的獲取異常資訊的方式外,還可以通過sys模組裡的exc_info()函式
獲得,使用程式碼示例如下:
import sys
try:
result = 1 / 0
except:
tuple_exception = sys.exc_info()
# 輸出結果依次是:異常類,類示例,跟蹤記錄物件
for i in tuple_exception:
print(i)
複製程式碼
執行結果如下:
<class 'ZeroDivisionError'>
division by zero
<traceback object at 0x000001E079360288>
複製程式碼
2、斷言
當 assert關鍵字
後面的判斷條件為假的時候,程式自動崩潰並丟擲AssertionErro異常。一般在測試程式的時候才會用到:需要確保某個條件為真程式才能正常工作的時候使用。
另外要和異常處理進行區分:
「異常處理」用於對程式發生異常情況的處理,以增加程式的健壯性和容錯性,而「斷言」則是用來檢查非法情況,用於幫助開發者快速定位問題位置。
Python中關於斷言assert的玩法有兩種:
- assert 判斷條件:如果判斷條件為false,就raise一個AssertionError
- assert 判斷條件,異常描述:如果判斷條件為false,就raise一個帶描述資訊的AssertionError
程式碼示例如下:
a, b = 1, 2
# 第一種斷言用法
assert a > b
# 第二種斷言用法
assert (a > b), ("{a} 並不比 {b} 大'".format(a = a, b = b))
複製程式碼
執行結果如下:
Traceback (most recent call last):
File "F:/Project/Python/Book/Chapter 7/7_1_10.py", line 5, in <module>
assert a > b
AssertionError
Traceback (most recent call last):
File "F:/Project/Python/Book/Chapter 7/7_1_10.py", line 6, in <module>
assert (a > b), ("{a} 並不比 {b} 大'".format(a = a, b = b))
AssertionError: 1 並不比 2 大'
複製程式碼
如果本文對你有所幫助,歡迎
留言,點贊,轉發
素質三連,謝謝?~