使用pdb交互式调试程序
创始人
2024-03-04 15:12:55
0

使用pdb交互式调试程序

1.概述

在调试程序时候,我们使用print输出调试信息的频率很高,但是这个方式效率却不高,有些时候追查程序出错原因也不是很方便。
这次我们要介绍python内置的交互式调试器,他可以检查程序状态,打印变量信息。

2.pdb介绍

在其他大部分语言中,如果要使用调试器,那么必须现在源文件中设置断点,让程序执行到这一行停下来然后调试程序。而python不用这样,他可以直接在假设有问题的代码位置上加一条指令到程序停下来,启动调试器。采用这种方法来调试程序与正常启动程序并没有什么区别。
尤其适合在没有IDE编辑器时,通过python命令界面调试运行中的代码非常的方便。

2.1.pdb基本操作

pdb调试代码支持在python命令界面使用和在IDE编辑器界面使用,下面介绍下在IDE编辑器中使用pdb调试器。

在pdb提示符操作界面,可以通过help查看所有操作命令。下面列出常用操作命令:

  • where简写w:输出当前代码运行的位置
  • up简写u:跳转到执行调用栈上一层,回到当前函数调用者位置方便查看调用者位置的变量信息。例如A调用B函数,在B函数中跳转到A的位置。
  • down简写d:跳转到执行调用栈下一层,例如A调用B函数,在A函数中跳转到B的位置。
  • step简写s:执行程序里面的下一行代码,如果下一行代码是个函数则会进入函数内部。
  • next简写n:执行程序里面的下一行代码,如果下一行代码是个函数则不会进入函数内部。
  • return简写r:让程序一直运行到当前函数的返回为止
  • continue简写c:让程序运行到下一个断点位置
  • quit简写q:退出调试界面
  • p 变量名称:输出变量值
  • 变量名称:可以直接输入变量名称,输出变量的值
  • locals():输出当前函数里面所有局部变量值

下面通过一个例子演示下操作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

2.2.事后调试器

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) 

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...