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