在调试程序时候,我们使用print输出调试信息的频率很高,但是这个方式效率却不高,有些时候追查程序出错原因也不是很方便。
这次我们要介绍python内置的交互式调试器,他可以检查程序状态,打印变量信息。
在其他大部分语言中,如果要使用调试器,那么必须现在源文件中设置断点,让程序执行到这一行停下来然后调试程序。而python不用这样,他可以直接在假设有问题的代码位置上加一条指令到程序停下来,启动调试器。采用这种方法来调试程序与正常启动程序并没有什么区别。
尤其适合在没有IDE编辑器时,通过python命令界面调试运行中的代码非常的方便。
pdb调试代码支持在python命令界面使用和在IDE编辑器界面使用,下面介绍下在IDE编辑器中使用pdb调试器。
在pdb提示符操作界面,可以通过help查看所有操作命令。下面列出常用操作命令:
下面通过一个例子演示下操作pdb命令调试程序。
import math
def compute_rmse(observed, ideal):
total_err_2 = 0
count = 0
for got, wanted in zip(observed, ideal):
err_2 = (got - wanted) ** 2
# 设置断点
breakpoint() # Start the debugger here
total_err_2 += err_2
count += 1
mean_err = total_err_2 / count
rmse = math.sqrt(mean_err)
return rmse
result = compute_rmse(
[1.8, 1.7, 3.2, 6],
[2, 1.5, 3, 5])
print(result)
运行上面的代码,他会停在断点的位置,然后通过pdb命令调试程序。
# 输出某个变量值
(Pdb) p err_2
0.03999999999999998
(Pdb) err_2
0.03999999999999998
# 输出当前函数中所有变量值
(Pdb) locals()
{'observed': [1.8, 1.7, 3.2, 6], 'ideal': [2, 1.5, 3, 5], 'total_err_2': 0, 'count': 0, 'got': 1.8, 'wanted': 2, 'err_2': 0.03999999999999998}
# 查看当前程序运行的位置
(Pdb) w
/Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/no_80.py(15)compute_rmse()
-> total_err_2 += err_2
# 运行到下一行代码
(Pdb) n
> /Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/no_80.py(16)compute_rmse()
-> count += 1
# 退出运行
(Pdb) q
pdb还支持一项有用的功能,叫做事后调试,我们发现程序抛出异常并崩溃后,想通过调试器看看它在抛出异常的那一刻,究竟发生了什么。
有时候我们不确定在哪里调用breakpoint函数,在这种情况下,尤其需要这项功能。
下面来看一个示例
在这个代码中调用compute_rmse函数传入了一个7j参数,会抛出异常。
import math
def compute_rmse(observed, ideal):
total_err_2 = 0
count = 0
for got, wanted in zip(observed, ideal):
err_2 = (got - wanted) ** 2
total_err_2 += err_2
count += 1
mean_err = total_err_2 / count
rmse = math.sqrt(mean_err)
return rmse
result = compute_rmse(
[1.8, 1.7, 3.2, 7j], # Bad input
[2, 1.5, 3, 5])
print(result)
运行上面代码,下面是异常信息
python3 -m pdb -c continue no_80.py
# m:调用pdb命令
# c:continue命令会让pdb在启动被测程序之后进入到断点位置,或运行到出现异常为止。
# 运行结果
TypeError: must be real number, not complex
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
还有另一种方式可以触发事后机制,在运行代码遇到未捕获的异常后,在代码中引入pdb模块并调用pm函数。
# 输入python3切换到python命令界面
localhost:python3
#导入模块
>>> import my_module
# 运行代码模块中的compute_stddev函数,下面是异常信息
>>> my_module.compute_stddev([5])
Traceback (most recent call last):
File "" , line 1, in <module>
File "/Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/my_module.py", line 20, in compute_stddev
variance = compute_variance(data)
File "/Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/my_module.py", line 16, in compute_variance
variance = err_2_sum / (len(data) - 1)
ZeroDivisionError: float division by zero
上面的代码抛出了异常,下面使用pdb
# 上面代码运行出现了异常信息,下面使用pdb查看错误信息。
>>> import pdb; pdb.pm()
> /Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/my_module.py(16)compute_variance()
-> variance = err_2_sum / (len(data) - 1)
# 上面报错是这行代码,variance = err_2_sum / (len(data) - 1),下面查看下变量值。
(Pdb) err_2_sum
0.0
(Pdb) len(data)
1
(Pdb)