Re: [問題] 找不出問題在哪裡

作者: ccwang002 (亮)   2015-03-21 16:58:34
你的問題蠻複雜的,不過我想能歸納成:
在某個迴圈中,做了些操作但跑出來的結果跟想像中不一樣
因為會在像 for loop 的結構中,如果不太清楚 bug 的位置,
可能就得用 print(...) debug 但每次 loop 都印很長。
此時可用 debugger 設定中斷點,檢查程式執行是不是如自己所想的。
pdb 是 Python 內建的 debugger,官方說明文件在
https://docs.python.org/3/library/pdb.html
我舉一個簡單的例子:
# url: https://gist.github.com/0f25f2dd4b59312925a1
import numpy as np
rs = np.random.RandomState(seed=5566)
n_conditions = 10
result_sum = 0.0
for i in range(n_conditions):
# assume complex_out is some complex computation
complex_out = rs.normal(loc=3.0, scale=0.8, size=1000)
# we found the result is not right sometimes
result_sum += np.sum(complex_out)
complex_out 用來模擬一個很複雜但有錯誤的計算,不同 i 想成是不同的輸入條件
正常時候 complex_out 每一項都是正的。錯誤就是負值的部份。
這邊的情境是錯的機會很小,我們想知道到底什麼情況 (i = 什麼的時候)
會算出錯的值。
pdb 可以這樣使用
PS > python3 -m pdb .\bogus_script.py
> c:\...\bogus_script.py(1)<module>()
-> import numpy as np
(Pdb)
就會進入 Pdb 互動式的介面,輸入 h 就可以看到操作說明。
這邊設定中斷點在 `result_sum ...` 這行(我的例子是 23 行)
同時我不想每次 loop 到這行都被中斷,可以設定有出現負值時再停下來,
看看到底這時候相關的變數值是什麼情況。
(Pdb) b 23, any(complex_out < 0)
Breakpoint 1 at c:\...\bogus_script.py:23
此時再輸入 c (continue) 會讓程式繼續執行到中斷點被觸發。
這個例子剛好有個負值出現,所以會被中斷。
這時候就可以用 p (print) 看一下情況 (i 是多少)
(Pdb) c
> c:\...\bogus_script.py(23)<module>()
-> result_sum += np.sum(complex_out)
(Pdb) p i
5
那就可以去看 i = 5 這情況的輸入會造成什麼問題。
也可以看錯的值到底是什麼
(Pdb) p complex_out[complex_out < 0]
array([-0.12264442])
按 q 退出 pdb。Pdb 常用的指令有:
p 印出東西 s 執行下一個操作(會進到函式中)
c 繼續執行 q 結束
n 執行到下一行 w 印出所在的 frame stack (例如呼叫了很多函式)
b 設定中斷點 u/d 上/下一層 frame(Ex A()->B()->C() 在 A B C 中移動)
簡單的 pdb 操作就這樣。在複雜一點的程式,很多人直接把開啟 pdb 寫在程式碼裡:
import pdb; pdb.set_trace()
到了這一行就會打開 pdb 進入 debug 環境。
用 IPython 的話可以設定有 uncaught exception 的時候自動進入 pdb
抓到發生錯誤的 frame:
In [1]: %pdb on
Automatic pdb calling has been turned ON
In [2]: def ride_eva(pilot):
...: if pilot == 'shinji':
...: raise SystemError('逃げちゃ駄目だ' * 20)
...:
In [3]: ride_eva('shinji')

Links booklink

Contact Us: admin [ a t ] ucptt.com