給自己的Python小筆記: Debug與測試好幫手- 嘗試try-except與主動引發raise與assert-程式異常處理

Chwang
9 min readMay 11, 2021

--

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來幫助我們做到好的錯誤管裡,讓程式專案可以順利開發下去,希望這次對大家有很大的幫忙,有任何問題都可以找我討論喔~~

Reference:
https://docs.python.org/3/library/exceptions.html

--

--

Chwang

YO~~ 大家好我是一名AI人工智慧領域的小小工程師, 熱愛自學, 熱愛分享, 下班後的我想為自己Coding, 積極撰寫教學文, 想將自學的程式知識分享給大家, 不斷追求進步的自己, 希望有一天能回饋社會,幫助需要幫助的人, 如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~