給自己的Python小筆記: Debug與測試好幫手- 嘗試try-except與主動引發raise與assert-程式異常處理
Yo~ 今天來記錄一下在程式專案開發時,非常非常重要的一個技能,它能幫助我們在開發的過程中找尋出錯的地方,使用它後,可以很快地知道出問題的地方在哪跟出現的問題是什麼,這樣就不用每次程式Run起來報錯,我還要從線索中找尋錯誤的原因,然後同事跑你的code出錯,你還要過去幫他看問題在哪裡
1. try except 為什麼要使用異常處理呢?
除了我上面講到的原因,最重要的原因是能幫助我們在開發的過程中,我們有時候是沒辦法預期會有哪些錯誤的,使用這個方法就能知道程式哪邊可能會有bug,也就能馬上修正,不要等到寫了一大堆code之後,才發現很多bug來的好解決
2. raise 為什麼要引發錯誤呢?
a. 在執行程式時,我們有時候需要在某些不是我們設定的條件下將程式中止,不然會造成不是我們預期的結果,然後我們可能還沒發現,但只要程式中止了,就能馬上知道哪裡有問題
b. 在撰寫測試程式時,有時候我需要確定這樣的input會讓程式報錯,也就能確保我程式的品質,不會產出不是我預期的結果
3. 簡單講解一下程式出現異常的狀況
a. 這時候結果就會是一個NameError,也就是說Tom並沒有被定義,怎麼知道它等不等於10
4. 錯誤類型分成兩大類: 語法錯誤 與 邏輯錯誤
a. 語法錯誤: 簡單來說就是Python沒有這種寫法,但你卻這樣寫,所出現的錯誤,這種錯誤一定不會通過,所以一開始就得修正好
i. 舉個小例子: 正確的寫法應該是print(“Welcome Tom!!”)和def run(): pass, 這樣的錯誤就稱為SyntaxError,也就是語法問題
b. 邏輯錯誤
i. 舉個例子: 例子中有NameError、ZeroDivisionError、TyeError、IndexError,當然還有想當多類型的Error,我下面會提到
5. 錯誤類型有哪些
a. 常見的錯誤
b. 完整的錯誤類型: 可以參考官方文檔
c. 錯誤類型結構
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
資料來源: https://docs.python.org/3/library/exceptions.html
小叮嚀: 錯誤類型不需要背下來,需要用到的時後,再查就好
6. try except else finally 用法
a. 格式
try:
要進行錯誤捕捉的程式碼
except 錯誤類型a as e: ##e 是用來記住錯誤資訊,可以不寫
如果程式發生錯誤類型為a,就會執行這裡
except 錯誤類型b:
如果錯誤類型為b,就會執行這裡
except (錯誤類型c, 錯誤類型d) as f: ## 用來同時捕捉多個錯誤
如果錯誤類型符合錯誤類型c與錯誤類型d,就會執行這邊
except Exception as e:
如果不知道會發生的錯誤類型為何,可以使用它,除了你寫下要捕捉的錯誤類型,其餘發生的錯誤都會執行這裡else:
如果沒有錯誤,就會執行這裡
finally:
不管有沒有錯誤都會執行這裡
b. 範例:
def try_test(person, salary):
people = ""
try:
if person != "Tom":
people = person + 'and ' + 'Jen'
total_month_for_house = 100 / salary
# except TypeError:
# print(“你輸入的類型應該要是字串喔!!”)
except Exception as e:
print("捕捉錯誤資訊: "+ str(e))
print("萬能用法: 當不知道會發生什麼錯誤時的捕捉錯誤方法")
else:
print("正確執行 :")
print("Hello "+people)
print("你的薪水需要"+str(total_month_for_house)+"個月來完成付款")
finally:
print("不管如何都會執行finally")
print("====================================")
執行結果:
7. raise與assert: 引發錯誤並中斷程式
a. 有時候一些不符合我們想要的情況發生時,我們需要強制將程式中斷,這時就需要raise與assert
b. raise
i. 格式: raise (錯誤類型)
ii. 舉例:
raise TypeError
c. assert
i. 格式: assert False, “中斷原因”
ii. 舉例:
assert False, “有錯,請檢察input data”
8. 程式裡面每個程式片段都使用try來查錯誤嗎?
雖然try-except是非常好用的錯誤處理方式,但是並不適合讓我們的程式佈滿try-except,這樣會讓我們的程式可讀性變低,導致維護上的困難,所以只要在容易出錯的程式上加上就可以囉
大家可以開始著手採用try-except、raise、assert來幫助我們做到好的錯誤管裡,讓程式專案可以順利開發下去,希望這次對大家有很大的幫忙,有任何問題都可以找我討論喔~~