Try   HackMD
tags: python

除錯與異常處理

例外

  • 語法錯誤(syntax error):不符合python程式撰寫規則
    • 沒有縮排
    • 拼錯python指令、參數格式不符合函數要求
    • 不管如何執行時一定會發生錯誤
    • 比較容易除錯
  • 執行期間錯誤(runtime error):執行程式時發生的錯誤
    • 使用者輸入預期以外的資料
    • 系統軟硬體出現異常
    • 執行時可能正常也可能發生錯誤,端看使用者輸入資料或操作而定
  • 邏輯錯誤(logic error):沒有任何錯誤訊息,但程式邏輯不符合商業邏輯
    • 使用者登入後可瀏覽其他使用者的檔案資訊

當錯誤發生時程式就被中斷並產生讓使用者害怕的錯誤畫面

範例1

x = int(input("input first num: ")) y = int(input("input second num: ")) z = x / y print(z)

透過tryexcept補抓錯誤狀態,導向使用者理解的錯誤訊息
並讓程式仍然可以正常繼續運作

範例2

while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) z = x / y except: print("error") print(z)

發生不同錯誤顯示不同錯誤訊息
讓錯誤訊息更加明確具體

範例3

while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) z = x / y print(z) except ZeroDivisionError: print("y can't be zero") except ValueError: print("please input number") except: print("error")

顯示python預設錯誤訊息

範例4

while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) z = x / y print(z) except ZeroDivisionError: print("y can't be zero") except Exception as e: print(e)

else: 當沒有發生任何錯誤時執行
finally: 不管有沒有發生錯誤都要執行這一行

範例5

count = 0 while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) z = x / y except Exception as e: print(e) else: print(z) finally: count += 1 print("count: ", count)

在開發函數、物件、套件時,我們會在開發者不正確使用時故意產生錯誤
提醒開發者錯誤發生在哪裡
避免開發者最後才知道不正確
而需要整個程式碼下去一個一個除錯
浪費大量成本

範例6

try: x = int(input('num: ')) if x >= 100: raise NameError("數字不可大於100") elif x < 0: raise NameError("數字不可小於0") except Exception as e: print(e)

日誌(log)

  • 可控制除錯訊息顯示或不顯示
  • 方便將除錯資訊寫入檔案

日誌等級

由高到低

  • 危急(critical):顯示發生系統或電腦嚴重當機時的資訊
  • 錯誤(error):顯示發生錯誤時的資訊
  • 警告(warning):顯示可能會發生錯誤時的資訊
  • 資訊(info):顯示一般事件發生時的資訊,例如執行某函數或觸發某事件
  • 除錯(debug):顯示關鍵變數變化的資訊

範例7

各位可以試者修改第三行,將logging.basicConfig(level=logging.DEBUG)
改成logging.basicConfig(level=logging.ERROR)
看看執行結果會有什麼變化

import logging logging.basicConfig(level=logging.DEBUG) logging.debug('DEBUG level message') logging.info('INFO level message') logging.warning('WARNING level message') logging.error('ERROR level message') logging.critical('CRITICAL level message')

範例8

import logging logging.basicConfig(level=logging.ERROR) while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) logging.debug("x: "+ str(x)) logging.debug("y: "+ str(y)) z = x / y print(z) except ZeroDivisionError: logging.error("y can't be zero") except Exception as e: logging.error(e)

範例9

透過logging.info顯示進入、離開函數showMsg訊息

#-*- coding:utf-8 -*- import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s: %(message)s') def showMsg(): logging.info('執行showMsg函數') print("hello") logging.info('結束showMsg函數') showMsg()

範例10

試者註解掉37~42行看看有什麼變化

import logging logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] %(levelname)s: %(message)s') class Animal: logging.info('run class Animal') def __init__(self, head, hand, foot): logging.info('run class Animal: __init__()') self.head = head self.hand = hand self.foot = foot def run(self): logging.info('run class Animal: run()') return '使用身體快速移動' class Bird(Animal): logging.info('run class Bird') def __init__(self, head, wing, foot): logging.info('run class Bird: __init__()') self.head = head self.wing = wing self.foot = foot def run(self): logging.info('run class Bird: run()') return '使用雙腳奔跑' def fly(self): logging.info('run class Bird: fly()') return '使用翅膀飛翔' if __name__ == '__main__': animal = Animal(1, 0, 4) print(animal.run()) bird = Bird(1, 2, 2) print(bird.run()) print(bird.fly())

格式化除錯訊息

範例11

#-*- coding:utf-8 -*- import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s: %(message)s') logging.debug('除錯訊息') logging.info('資訊訊息') logging.warning('警告訊息') logging.error('錯誤訊息') logging.critical('危急訊息')

輸出除錯訊息到檔案

範例12

import logging logging.basicConfig(level=logging.DEBUG, filename='debug.log', format='%(asctime)s - %(levelname)s: %(message)s') while True: try: x = int(input("input first num: ")) y = int(input("input second num: ")) logging.debug("x: "+ str(x)) logging.debug("y: "+ str(y)) z = x / y print(z) except ZeroDivisionError: logging.error("y can't be zero") except Exception as e: logging.error(e)