在调试程序时候,我们使用print输出调试信息的频率很高,但是这个方式效率却不高,有些时候追查程序出错原因也不是很方便。
这次我们要介绍python内置的交互式调试器,他可以检查程序状态,打印变量信息。
在其他大部分语言中,如果要使用调试器,那么必须现在源文件中设置断点,让程序执行到这一行停下来然后调试程序。而python不用这样,他可以直接在假设有问题的代码位置上加一条指令到程序停下来,启动调试器。采用这种方法来调试程序与正常启动程序并没有什么区别。
尤其适合在没有IDE编辑器时,通过python命令界面调试运行中的代码非常的方便。
pdb调试代码支持在python命令界面使用和在IDE编辑器界面使用,下面介绍下在IDE编辑器中使用pdb调试器。
在pdb提示符操作界面,可以通过help查看所有操作命令。下面列出常用操作命令:
下面通过一个例子演示下操作pdb命令调试程序。
import mathdef compute_rmse(observed, ideal):total_err_2 = 0count = 0for got, wanted in zip(observed, ideal):err_2 = (got - wanted) ** 2# 设置断点breakpoint() # Start the debugger heretotal_err_2 += err_2count += 1mean_err = total_err_2 / countrmse = math.sqrt(mean_err)return rmseresult = 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 mathdef compute_rmse(observed, ideal):total_err_2 = 0count = 0for got, wanted in zip(observed, ideal):err_2 = (got - wanted) ** 2total_err_2 += err_2count += 1mean_err = total_err_2 / countrmse = math.sqrt(mean_err)return rmseresult = 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 File "/Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/my_module.py", line 20, in compute_stddevvariance = compute_variance(data)File "/Users/edy/Documents/pythonwork/pyproject/flask_restX/src/app/suggest90/my_module.py", line 16, in compute_variancevariance = 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)