O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

除錯、測試與效能

214 visualizações

Publicada em

使用 pdb 模組除錯
對程式進行單元測試
使用 timeit 評測程式片段
使用 cProfile(profile)察看評測數據

Publicada em: Tecnologia
  • Seja o primeiro a comentar

除錯、測試與效能

  1. 1. 12. 除錯、測試與效能 • 學習目標 – 使用 pdb 模組除錯 – 對程式進行單元測試 – 使用 timeit 評測程式片段 – 使用 cProfile(profile) 察看評測數據 2
  2. 2. 除錯 • 檢測錯誤的時候,有個順手的工具可以加 速錯誤的檢出,其中 Debugger 是最常使 用也是最基本的工具之一 – 中斷點 – 檢視變數 – 逐步執行 3
  3. 3. 4
  4. 4. 5
  5. 5. 6
  6. 6. • Step Over 就是執行程式碼的下一步,如 果下步是個函式,會執行完該函式至返回 • 使用 Step Into,若下一步是個函式呼叫, 就會進入函式逐步執行,以便查看函式中 的演算與每一步執行結果 • 如果目前正在某個函式之中,接下來不想 逐步檢視函式中剩餘之程式碼,可以執行 Step Out 7
  7. 7. 使用 pdb 模組 • 如果手邊正好沒有整合開發環境,只能在 文字模式下執行程式進行除錯,那麼可以 使用 Python 內建的 pdb 模組 • 直接使用 python -m pdb,指定想要除 錯的 .py 檔案 8
  8. 8. 9
  9. 9. 10
  10. 10. 11
  11. 11. 12
  12. 12. • 如果想要單點針對某個函式進行除錯,可 以使用 pdb.run()函式,通常可以在 REPL 中進行這類動作 13
  13. 13. 14
  14. 14. • 可以將 pdb.set_trace() 直接撰寫在原 始碼中,當程式執行到 pdb.set_trace() 時,就會進入 (Pdb) 指令提示 • 若程式因為例外而無法繼續下去的話,可 以再使用 pdb.pm() 回到例外發生時的上 一步 15
  15. 15. 16
  16. 16. 17
  17. 17. 測試 • Python 變數沒有型態,如果有型態上的操 作錯誤,基本上會是在執行時期運行至該 段程式碼時,才會產生錯誤訊息 • 檢查出型態不正確的任務,必須由開發者 來承擔,而減輕這個負擔的最好方式之一, 就是撰寫良好的測試程式 18
  18. 18. • 撰寫測試的相關工具 – assert – doctest – unittest – 第三方測試工具(像是 nose、pytest 等) 19
  19. 19. • 要在程式中安插斷言,可以使用 assert • 使用 assert expression 的話,相當於 以下的程式片段: • 如果有兩個 expression,例如 assert expression1, expression2: 20
  20. 20. • __debug__ 是個內建變數,一般情況下會 是 True • 如果執行時需要最佳化時(在執行時加上- O 引數)則會是 False 21
  21. 21. 22
  22. 22. • 何時該使用斷言呢? – 前置條件斷言客戶端呼叫函式前,已經準備好 某些條件。 – 後置條件驗證客戶端呼叫函式後,具有函式承 諾之結果。 – 類別不變量(Class invariant)驗證物件某個 時間點下的狀態。 – 內部不變量(Internal invariant)使用斷言取 代註解。 – 流程不變量(Control-flow invariant)斷言程 式流程中絕不會執行到的程式碼部份。 23
  23. 23. 24
  24. 24. 25
  25. 25. 26
  26. 26. 撰寫 doctest • doctest 模組一方面是測試程式碼,一方 面也用來確認 DocStrings 的內容沒有過期 • 使用互動式的範例來執行驗證,開發者只 要為套件撰寫 REPL 形式的文件就可以 27
  27. 27. 28
  28. 28. 29
  29. 29. • 獨立地撰寫在另一個文字檔案中 30
  30. 30. 31
  31. 31. 使用 unittest 單元測試 • unittest 模組有時亦稱為"PyUnit",是 JUnit 的Python 語言實現 • JUnit 是個 Java 實現的單元測試(Unit test)框架 • 單元測試指的是測試一個工作單元(a unit of work)的行為 32
  32. 32. • 測試一個單元,基本上要與其他的單元獨 立,否則會是在同時測試兩個單元的正確 性,或是兩個單元之間的合作行為 • 就軟體測試而言,單元測試通常指的是測 試某個函式(或方法) 33
  33. 33. • unittest 模組主要包括四個部份: – 測試案例(Test case) – 測試設備(Test fixture) – 測試套件(Test suite) – 測試執行器(Test runner) 34
  34. 34. 測試案例 35
  35. 35. 36
  36. 36. 測試設備 • 如果有定義 setUp() 方法,那麼執行每個 test 開頭的方法前,都會呼叫一次 setUp() • 如果有定義 tearDown()方法,那麼執行 每個 test 開頭的方法後,都會呼叫一次 tearDown() • 可以使用 setUp()、tearDown()來分別 定義每次單元測試前後的資源建立與銷毀 37
  37. 37. 測試套件 • 想要將不同的測試組合在一起 • 想要自動載入某個 TestCase 子類別中所 有 test_xxx 方法 38
  38. 38. • 將某個測試套件與某個 TestCase 中的 test_xxx 方法組合為另一個測試套件: • 將許多測試套件再全部組合為另一個測試 套件: 39
  39. 39. 測試執行器 • 在程式碼中直接使用 TextTestRunner: • 在命令列中使用 unittest 模組來運行模 組、類別或甚至個別的測試方法: 40
  40. 40. timeit 模組 • 用來量測一個小程式片段的執行時間 41
  41. 41. • 到底是使用 + 時比較快,還是 join() 比 較快呢? 42
  42. 42. 43
  43. 43. • 效能是整體程式結合之後的執行考量,並 不是單一元素快慢的問題,也不是憑空猜 測,而是要有實際的評測作為依據 • timeit 預設是執行程式片段 1,000,000 次, 然後取平均時間 • 執行次數可透過 number 參數控制 44
  44. 44. • 以下是幾個直接透過 API 運行的範例: 45
  45. 45. 46
  46. 46. 使用 cProfile(profile) • cProfile 用來收集程式執行時的一些時 間數據,提供各種統計數據,對大多數的 使用者來說是不錯的工具 • 這是用 C 撰寫的擴充模組,在評測時有較 低的額外成本,不過並不是所有系統上都 有提供 • profile 介面上仿造了cProfile,是用 純Python 來實現的模組,因此有較高的互 通性 47
  47. 47. 48
  48. 48. • ncalls:"number of calls"的縮寫,也就是對 特定函式的呼叫次數。 • tottime:"total time"的縮寫,花費在函式上 的執行時間(不包括子函數 • 呼叫的時間)。 • percall:tottime 除以ncalls 的結果。 • cumtime:"cumulative time"的縮寫,花費 在函式與所有子函式的時間 • (從呼叫至離開)。 • percall:cumtime 除以ncalls 的結果。 • filename:lineno(function):提供程式碼執行 時的位置資訊。 49
  49. 49. • 可以使用 pstats 對 cProfile 的結果, 進行各種運算與排序 50

×