Python基礎知識(20):錯誤、除錯和測試
一、錯誤處理
在執行程式的過程中有可能會出錯,一般我們會在新增一段程式碼在可能出錯的地方,返回約定的值,就可以知道會不會出錯以及出錯的原因
1、使用try……except……finally……錯誤處理機制
try…可能會出異常的程式碼
except…如果try後面的程式碼出錯,則執行這裡的語句;否則直接執行finally語句
finally…無論try語句是否出錯都會執行
try: z=5/0 print("ressult=",zip) except ZeroDivisionError: print("The second number can`t be number!") finally: print("I`m here.") The second number can`t be number! I`m here.
多個except語句
try: z=5/5 print("ressult=",z) except ValueError as e: print(`ValueError:`, e) except ZeroDivisionError as e: print(`ZeroDivisionError:`, e) else: print(`No error!`) finally: print("I`m here.")
2、記錄錯誤
使用logging模組可以記錄出錯資訊
通過配置,可以讓logging記錄出錯的資訊到日誌,以便日後排查
#testlog.py
import logging def test(x): return 5/int(x) def main(): try: test("0") except Exception as e: logging.exception(e) main() print("END")
同樣是出錯,但程式列印完錯誤資訊後會繼續執行,並正常退出
ERROR:root:division by zero Traceback (most recent call last): File "D:/Python/doit/testLog.py", line 7, in main test("0") File "D:/Python/doit/testLog.py", line 4, in test return 5/int(x) ZeroDivisionError: division by zero END
3、丟擲錯誤
使用raise語句
如果要丟擲錯誤,首先根據需要,可以定義一個錯誤的class,選擇好繼承關係,然後,用raise
語句丟擲一個錯誤的例項
#testError class testError(ValueError): pass def test(x): y = int(x) if y==0: raise testError(`invalid value: %s` % x) return 10 / y test(`0`) Traceback (most recent call last): File "D:/Python/doit/testError.py", line 11, in <module> test(`0`) File "D:/Python/doit/testError.py", line 8, in test raise testError(`invalid value: %s` % x) testError: invalid value: 0
注:只有為完成某些需要時我們才自己定義錯誤型別,日常一般使用Python內建的錯誤型別
二、除錯
1、用print列印能出錯的變數
2、斷言assert
使條件為真,保證程式正常執行下去,否則丟擲AssertionError
可以在條件後新增字串,用來解釋斷言
def test(x): y=int(x) assert y!=0,"y is zero" return 5/y def main(): test("0") main() Traceback (most recent call last): ...... AssertionError: y is zero
3、logging
允許指定記錄出錯資訊的日誌級別等級:critical > error > warning > info > debug
#logErro.py import logging logging.basicConfig(level=logging.INFO) x="0" y=int(x) ogging.info("y=%d"%y) print(5/y) Traceback (most recent call last): File "D:/Python/doit/logErro.py", line 6, in <module> ogging.info("y=%d"%y) NameError: name `ogging` is not defined
4、pdb
Python偵錯程式,需要單步執行
5、pdb.set_trace
這個方法也是用pdb,但是不需要單步執行,只需要import pdb
,然後在可能出錯的地方放一個pdb.set_trace()
,就可以設定一個斷點
6、IDE
可以設定斷點、單步執行
需要安裝Python IDE
三、測試
單元測試
單元測試是用來對一個模組、一個函式或者一個類來進行正確性檢驗的測試工作
這種以測試為驅動的開發模式最大的好處就是確保一個程式模組的行為符合我們設計的測試用例。在將來修改的時候,可以極大程度地保證該模組行為仍然是正確的
單元測試可以有效地測試某個程式模組的行為,是未來重構程式碼的信心保證
單元測試的測試用例要覆蓋常用的輸入組合、邊界條件和異常
單元測試程式碼要非常簡單,如果測試程式碼太複雜,那麼測試程式碼本身就可能有bug
單元測試通過了並不意味著程式就沒有bug了,但是不通過程式肯定有bug
setUp與tearDown
可以在單元測試中編寫兩個特殊的setUp()
和tearDown()
方法。這兩個方法會分別在每呼叫一個測試方法的前後分別被執行
文件測試
Python內建的“文件測試”(doctest)模組可以直接提取註釋中的程式碼並執行測試
當模組正常匯入時,doctest不會被執行。只有在命令列直接執行時,才執行doctest。所以,不必擔心doctest會在非測試環境下執行
doctest非常有用,不但可以用來測試,還可以直接作為示例程式碼。通過某些文件生成工具,就可以自動把包含doctest的註釋提取出來。使用者看文件的時候,同時也看到了doctes