python自产调试工具pdb的使用
python自产调试工具pdb的使用
介绍
- 调试打印在写代码的时候不可避免
- 项目越大,调试可能花的时间会越多
- print调试可能是最早用的,一段时间内你都会习惯这种方式
- 一旦成了老鸟,你应该会去用IDE的debugger,功能非常强大,效率就比print上了一个台阶
- 当然python像其他语言一样,也有自己的调试工具,pdb
- python debugger:目的无非是为了知道程序此时的状态(在做啥,环境信息),当然它还要能暂停你的程序
调测代码
以LeetCode 1. 两数之和 为例
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示: # 下面的这些不考虑
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
我写个错误的代码
demo_twosum.py
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i,v in enumerate(nums):
if target-v in nums:
return [i,nums.index(target-v)]
对于以下cases,应返回[1,2],实际返回[0,0]
输入:nums = [3,2,4], target = 6
因为题目中有要求:
数组中同一个元素在答案里不能重复出现
pdb调试
切入pdb的方式
我们来看看如何用pdb来调试这段代码
from typing import List
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i,v in enumerate(nums):
if target-v in nums:
return [i,nums.index(target-v)]
nums = [3,2,4]
target = 6
solution = Solution().twoSum(nums,target)
print(solution)
你可以执行
python -m pdb demo_twosum.py
执行界面大致如下
# python -m pdb demo_twosum.py
> demo_twosum.py(1)<module>()
-> from typing import List
你还可以在代码中加
breakpoint()
if target-v in nums:
breakpoint() # 加在你要调试的代码附近 Line 7
return [i,nums.index(target-v)]
运行你的代码提示如下
D:\Python39\python.exe demo_twosum.py
> demo_twosum.py(7)twoSum()
-> return [i,nums.index(target-v)]
(Pdb)
常用的调试命令
典型的操作
D:\pythonProject\外部公开课\当前公开课>python -m pdb demo_twosum.py
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(1)<module>()
-> from typing import List
(Pdb) b 5
Breakpoint 1 at d:\pythonproject\外部公开课\当前公开课\demo_twosum.py:5
(Pdb) c
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(5)twoSum()
-> if target-v in nums:
(Pdb) w
d:\python39\lib\bdb.py(580)run()
-> exec(cmd, globals, locals)
<string>(1)<module>()
d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(9)<module>()
-> solution = Solution().twoSum(nums,target)
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(5)twoSum()
-> if target-v in nums:
(Pdb) p i
0
(Pdb) p target
6
(Pdb) p v
3
(Pdb) r
--Return--
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(6)twoSum()->[0, 0]
-> return [i,nums.index(target-v)]
(Pdb) l
1 from typing import List
2 class Solution:
3 def twoSum(self, nums: List[int], target: int) -> List[int]:
4 for i,v in enumerate(nums):
5 B if target-v in nums:
6 -> return [i,nums.index(target-v)]
7 nums = [3,2,4]
8 target = 6
9 solution = Solution().twoSum(nums,target)
10 print(solution)
[EOF]
(Pdb) p [i,nums.index(target-v)]
[0, 0]
(Pdb) q
所以,这是在做啥?
逐行解释
第1行
D:\pythonProject>python -m pdb demo_twosum.py
> d:\pythonproject\demo_twosum.py(1)<module>()
-> from typing import List
当前文件绝对路径 d:\pythonproject\demo_twosum.py
处于第一行 (1)
是个module
<module>()
第一行的内容 -> from typing import List # 这是你即将运行的代码
参考上面
breakpoint()
的方式,你会发现显示的是你打了断点下面的那一行代码。-> return [i,nums.index(target-v)]
第2行
(Pdb) b 5
Breakpoint 1 at d:\pythonproject\外部公开课\当前公开课\demo_twosum.py:5
- 在第5行设置一个断点
- 如果就写一个b(break),那就是列出当前所有的断点
- 对应的
clear 断点编号
就可以取消该断点
第3行
(Pdb) c
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(5)twoSum()
-> if target-v in nums:
- 运行到设置的断点处
第4行
(Pdb) w
d:\python39\lib\bdb.py(580)run()
-> exec(cmd, globals, locals)
<string>(1)<module>()
d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(9)<module>()
-> solution = Solution().twoSum(nums,target)
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(5)twoSum()
-> if target-v in nums:
- 查看当前的调用栈
- 是不是有点像堆栈的打印
第5行
(Pdb) p i
0
(Pdb) p target
6
(Pdb) p v
3
打印当前的变量
pp则是类似于pprint,美化输出
注意p可以打印任意有效的python表达式
值得一提的是,你甚至可以改变此时的程序(print做不到了)
# 比如 任意的python 语句
v = 3
第6行
(Pdb) r
--Return--
> d:\pythonproject\外部公开课\当前公开课\demo_twosum.py(6)twoSum()->[0, 0]
-> return [i,nums.index(target-v)]
- 运行到返回
第7行
(Pdb) l
- 打印当前位置前后11行代码
- 再输入一个l,则往下再翻11行
l.
可以列出当前行周围的 11 行
第8行:打印
[i,nums.index(target-v)]
,发现是[0,0]第9行:q,退出
附录 pdb命令全解
h(elp) [command]
不带参数时,显示可用的命令列表。参数为 command 时,打印有关该命令的帮助。
help pdb
显示完整文档(即pdb
模块的文档字符串)。由于 command 参数必须是标识符,因此要获取!
的帮助必须输入help exec
。w(here)
打印堆栈回溯,最新一帧在底部。有一个箭头指向当前帧,该帧决定了大多数命令的上下文。
d(own) [count]
在堆栈回溯中,将当前帧向下移动 count 级(默认为 1 级,移向更新的帧)。
u(p) [count]
在堆栈回溯中,将当前帧向上移动 count 级(默认为 1 级,移向更老的帧)。
b(reak) [([filename:]lineno | function) [, condition]]
如果带有 lineno 参数,则在当前文件相应行处设置一个断点。如果带有 function 参数,则在该函数的第一条可执行语句处设置一个断点。行号可以加上文件名和冒号作为前缀,以在另一个文件(可能是尚未加载的文件)中设置一个断点。另一个文件将在
sys.path
范围内搜索。请注意,每个断点都分配有一个编号,其他所有断点命令都引用该编号。如果第二个参数存在,它应该是一个表达式,且它的计算值为 true 时断点才起作用。如果不带参数执行,将列出所有中断,包括每个断点、命中该断点的次数、当前的忽略次数以及关联的条件(如果有)。tbreak [([filename:]lineno | function) [, condition]]
临时断点,在第一次命中时会自动删除。它的参数与
break
相同。cl(ear) [filename:lineno | bpnumber ...]
如果参数是 filename:lineno,则清除此行上的所有断点。如果参数是空格分隔的断点编号列表,则清除这些断点。如果不带参数,则清除所有断点(但会先提示确认)。
disable [bpnumber ...]
禁用断点,断点以空格分隔的断点编号列表给出。禁用断点表示它不会导致程序停止执行,但是与清除断点不同,禁用的断点将保留在断点列表中并且可以(重新)启用。
enable [bpnumber ...]
启用指定的断点。
ignore bpnumber [count]
为指定的断点编号设置忽略次数。如果省略 count,则忽略次数将设置为 0。忽略次数为 0 时断点将变为活动状态。如果为非零值,在每次达到断点,且断点未禁用,且关联条件计算值为 true 的情况下,该忽略次数会递减。
condition bpnumber [condition]
为断点设置一个新 condition,它是一个表达式,且它的计算值为 true 时断点才起作用。如果没有给出 condition,则删除现有条件,也就是将断点设为无条件。
commands [bpnumber]
为编号是 bpnumber 的断点指定一系列命令。命令内容将显示在后续的几行中。输入仅包含
end
的行来结束命令列表。举个例子:(Pdb) commands 1 (com) p some_variable (com) end (Pdb)
要删除断点上的所有命令,请输入commands
并立即以end
结尾,也就是不指定任何命令。如果不带 bpnumber 参数,commands
作用于最后一个被设置的断点。可以为断点指定命令来重新启动程序。只需使用continue
或step
命令或其他可以继续运行程序的命令。如果指定了某个继续运行程序的命令(目前包括continue
,step
,next
,return
,jump
,quit
及它们的缩写)将终止命令列表(就像该命令后紧跟着 end)。因为在任何时候继续运行下去(即使是简单的 next 或 step),都可能会遇到另一个断点,该断点可能具有自己的命令列表,这导致要执行的列表含糊不清。如果在命令列表中加入 'silent' 命令,那么在该断点处停下时就不会打印常规信息。如果希望断点打印特定信息后继续运行,这可能是理想的。如果没有其他命令来打印一些信息,则看不到已达到断点的迹象。s(tep)
运行当前行,在第一个可以停止的位置(在被调用的函数内部或在当前函数的下一行)停下。
n(ext)
继续运行,直到运行到当前函数的下一行,或当前函数返回为止。(
next
和step
之间的区别在于,step
进入被调用函数内部并停止,而next
(几乎)全速运行被调用函数,仅在当前函数的下一行停止。)unt(il) [lineno]
如果不带参数,则继续运行,直到行号比当前行大时停止。如果带有行号,则继续运行,直到行号大于或等于该行号时停止。在这两种情况下,当前帧返回时也将停止。在 3.2 版更改: 允许明确给定行号。
r(eturn)
继续运行,直到当前函数返回。
c(ont(inue))
继续运行,仅在遇到断点时停止。
j(ump) lineno
设置即将运行的下一行。仅可用于堆栈最底部的帧。它可以往回跳来再次运行代码,也可以往前跳来跳过不想运行的代码。需要注意的是,不是所有的跳转都是允许的 -- 例如,不能跳转到
for
循环的中间或跳出finally
子句。l(ist) [first[, last]]
列出当前文件的源代码。如果不带参数,则列出当前行周围的 11 行,或继续前一个列表。如果用
.
作为参数,则列出当前行周围的 11 行。如果带有一个参数,则列出那一行周围的 11 行。如果带有两个参数,则列出所给的范围中的代码;如果第二个参数小于第一个参数,则将其解释为列出行数的计数。当前帧中的当前行用->
标记。如果正在调试异常,且最早抛出或传递该异常的行不是当前行,则那一行用>>
标记。3.2 新版功能:>>
标记。ll | longlist
列出当前函数或帧的所有源代码。相关行的标记与
list
相同。3.2 新版功能.a(rgs)
打印当前函数的参数列表。
p expression
在当前上下文中运行 expression 并打印它的值。注解
print()
也可以使用,但它不是一个调试器命令 --- 它执行 Pythonprint()
函数。pp expression
whatis expression
打印 expression 的类型。
source expression
尝试获取给定对象的源代码并显示出来。3.2 新版功能.
display [expression]
如果表达式的值发生改变则显示它的值,每次将停止执行当前帧。不带表达式则列出当前帧的所有显示表达式。3.2 新版功能.
undisplay [expression]
不再显示当前帧中的表达式。 不带表达式则清除当前帧的所有显示表达式。3.2 新版功能.
interact
启动一个交互式解释器(使用
code
模块),它的全局命名空间将包含当前作用域中的所有(全局和局部)名称。3.2 新版功能.alias [name [command]]
创建一个标识为 name 的别名来执行 command。 执行的命令 不可 加上引号。 可替换形参可通过
%1
,%2
等来标示,而%*
会被所有形参所替换。 如果没有给出命令,则会显示 name 的当前别名。 如果没有给出参数,则会列出所有别名。别名允许嵌套并可包含能在 pdb 提示符下合法输入的任何内容。 请注意内部 pdb 命令 可以 被别名所覆盖。 这样的命令将被隐藏直到别名被移除。 别名会递归地应用到命令行的第一个单词;行内的其他单词不会受影响。作为示例,这里列出了两个有用的别名(特别适合放在.pdbrc
文件中):# Print instance variables (usage "pi classInst") alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k]) # Print instance variables in self alias ps pi self
unalias name
删除指定的别名。
! statement
在当前堆栈帧的上下文中执行 (单行) statement。 感叹号可以被省略,除非语句的第一个单词与调试器命令重名。 要设置全局变量,你可以在同一行上为赋值命令添加前缀的
global
语句,例如:(Pdb) global list_options; list_options = ['-l'] (Pdb)
run [args ...]
restart [args ...]
重启被调试的 Python 程序。 如果提供了参数,它会用
shlex
来拆分且拆分结果将被用作新的sys.argv
。 历史、中断点、动作和调试器选项将被保留。restart
是run
的一个别名。q(uit)
退出调试器。 被执行的程序将被中止。
debug code
进入一个对代码参数执行步进的递归调试器(该参数是在当前环境中执行的任意表达式或语句)。
retval
打印函数最后一次返回的返回值。
python自产调试工具pdb的使用的更多相关文章
- python 内置调试工具 pdb
除了 pycharm 可以调试python外,python自带的内置工具pdb 也可以调试 python.其命令方式类似于 gdb. pdb 常用的调试命令见下表. 命令 解释 break 或 b 设 ...
- 12、python单步调试工具pdb
pdb 第4种方式是启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态.我们先准备好程序: # err.py s = '0' n = int(s) print(10 / n) ...
- pytorch Debug —交互式调试工具Pdb (ipdb是增强版的pdb)-1-使用说明
初学时大多使用print或log调试程序,这在小规模的程序下很方便 但是更好的方法是一边运行一边检查里面的变量和方法 1.Pdb Pdb是一个交互式的调试工具,集成于Python标准库中 Pdb能让你 ...
- 『无为则无心』Python基础 — 4、Python代码常用调试工具
目录 1.Python的交互模式 2.IDLE工具使用说明 3.Sublime3工具的安装与配置 (1)Sublime3的安装 (2)Sublime3的配置 4.使用Sublime编写并调试Pytho ...
- python调试工具pdb
pdb是基于命令行的调试工具,非常类似gnu的gdb(调试c/c++). 命令 简写命令 作用 break b 设置断点 continue c 继续执行程序 list l 查看当前行的代码段 step ...
- python执行命令行调试工具pdb
调试 pdb pdb是基于命令行的调试工具,非常类似gnu的gdb(调试c/c++). 命令 简写命令 作用 break b 设置断点(用法,b <数字>:在第数字行设置断点....... ...
- Python自带又好用的代码调试工具Pdb学习笔记
返璞归真 这几天项目有一个linux下部署数据库的操作,数据库使用python进行初始化安装.然后问题来了,由于linux服务器涉及安全要求,除了代码以来的Python3.6版本外不允许安装其他插件与 ...
- Python原生调试工具pdb实践小结
使用python -m pdb xxx.py进入单步调试模式,默认会在脚本的第一行可执行命令处停止.此时,通过 b function设置之后的函数断点会提示出错,从出错异常栈中可以看出,pdb是将fu ...
- 【Python】debug工具-pdb(转)
Debug功能对于developer是非常重要的,python提供了相应的模块pdb让你可以在用文本编辑器写脚本的情况下进行debug. pdb是python debugger的简称. 常用的一些命令 ...
- pytorch Debug —交互式调试工具Pdb (ipdb是增强版的pdb)-1-在pytorch中使用
参考深度学习框架pytorch:入门和实践一书第六章 以深度学习框架PyTorch一书的学习-第六章-实战指南为前提 在pytorch中Debug pytorch作为一个动态图框架,与ipdb结合能为 ...
随机推荐
- C# winform DataGridView 一列显示星号
private void myDataGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventA ...
- Web服务器2
Web服务器2 基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用Linux Socket实现: Web服务器的客户端服务器,提交程序运行截图 实现GET即可,请求,响应要符合HTTP协议规范 ...
- listener.log/listener_scan1.log监听日志太大清理
listener_scan1.log清理lsnrctlset current_listener listener_scan1show log_statusset log_status offcd /u ...
- 打印机出现错误0x00000709要如何解决
就是微软2021年10月更新的这个补丁导致的 要卸载KB5006670. 原文:https://www.zhihu.com/question/298855357/answer/514515054 微软 ...
- SpringBoot整合RocketMQ案例实战
一.概念 rocketMQ是一款典型的分布式架构下的中间件产品,使用异步通信方式和发布订阅的消息传输模型,具备异步通信的优势,系统拓扑简单,上下游耦合较弱,主要应用于异步解耦,流量削峰填谷等场景 二. ...
- MS-08-067 windows smb服务 远程命令执行漏洞
漏洞概要 MS-08-067是Windows平台中smb服务445端口的远程代码执行漏洞 利用成功可以远程控制主机 影响范围为:windows2000.xp.server 2003.server 20 ...
- linux网络编程中的errno处理
在Linux网络编程中,errno是一个非常重要的变量.它记录了最近发生的系统调用错误代码.在编写网络应用程序时,合理处理errno可以帮助我们更好地了解程序出现的问题并进行调试. 通常,在Linux ...
- Tars-Java网络编程源码分析
作者:vivo 互联网服务器团队- Jin Kai 本文从Java NIO网络编程的基础知识讲到了Tars框架使用NIO进行网络编程的源码分析. 一.Tars框架基本介绍 Tars是腾讯开源的支持多语 ...
- Kubernetes 的亲和性污点与容忍
写在前面 我们在使用k8s过程中经常有这样的需求:我的k8s集群有多台服务器,配置不尽相同.我想把数据库部署到CPU.内存比较好的这几台机:我想把静态承载服务部署到有固态硬盘的机器等:而这些需求,就是 ...
- 关于VScode vue3卡顿
在使用vscode+volar开发vue3项目时,出现代码提示缓慢的问题.通过开启Volar Takeover *模式解决. 以下摘自Vue3官网 https://cn.vuejs.org/guide ...