iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python调试工具pdb怎么使用
  • 824
分享到

python调试工具pdb怎么使用

2023-07-04 13:07:36 824人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要讲解了“python调试工具pdb怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python调试工具pdb怎么使用”吧!一、pdb 有2种用法pdb:python deb

这篇文章主要讲解了“python调试工具pdb怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python调试工具pdb怎么使用”吧!

一、pdb 有2种用法

pdb:python debugger

1、非侵入式方法 (不用额外修改源代码,在命令行下直接运行就能调试)

python3 -m pdb filename.py

2、侵入式方法 (需要在被调试的代码中添加以下代码然后再正常运行代码)

import pdbpdb.set_trace()

当你在命令行看到下面这个提示符时,说明已经正确打开了pdb

(Pdb)

二、pdb 基本命令

命令解释
break 或 b设置断点
continue 或 c继续执行程序
list 或 l查看当前行的代码段
step 或 s进入函数(进入 for 循环用 next 而不是用 step)
return 或 r执行代码直到从当前函数返回
next 或 n执行下一行
up 或 u返回到上个调用点(不是上一行)
p x打印变量x的值
exit 或 q中止调试,退出程序
help帮助

在实际使用中发现,用shell脚本运行python文件时,可能无法用pdb调试,会退出。此时只能直接运行py文件来调试。

三、在指定文件的指定位置,用break命令设置断点

3.1 在本文件中的指定位置设置断点

比如下面的例子,要想进入到模型的 forward() 方法中查看前向传播过程中的数据处理过程,只能在  forward() 的第一行(即26行)设置断点,pdb.set_trace()

但有时候模型很复杂,用这种方法会导致程序报错直接退出(我也不知道是什么原因),那么我们就可以考虑用 break 命令在这一行插入断点,使得程序运行到 forward() 时就会停下来。

import torchimport torch.nn as nnimport pdbclass EncoderLayer(nn.Module):    def __init__(self):        super().__init__()        self.conv1 = nn.Conv2d(4, 10, (3, 3))        self.conv2 = nn.Conv2d(10, 4, (3, 3))        self.relu = nn.ReLU()    def forward(self, x):        x=self.relu(self.conv1(x))        return self.relu(self.conv2(x))class Encoder(nn.Module):    def __init__(self,num_layers):        super().__init__()        # encoders 由 num_layers个 EncoderLayer子层组成,每个子层结构相同,但参数不一定相同。        self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)])    def forward(self, x):        # ModuleList是一个list,只能通过list的操作方式(如用for循环、下标索引等)进行forward计算。        for layer in self.ModelList:            x = layer(x)        return xif __name__=="__main__":    pdb.set_trace()       input = torch.rand(5, 4, 30, 30)    model = Encoder(num_layers=4)    output = model(input)

具体方法:(1)首先在前面的任意一行设置 pdb.set_trace() ,使得程序停下来。(2)输入 break 26 就可以了。如图:

python调试工具pdb怎么使用这样断点就设置成功了,程序运行到forward()就会停下来。

这里的26是行数,需要注意的是 断点位置不能是注释,比如我们在25行(注释行)设置断点,就会失败:

python调试工具pdb怎么使用总结一下,在同一个文件中设置断点的命令是:

break line

3.2 在其他文件中的指定位置设置断点

如果想要设置的断点不在初始运行文件里面呢,怎么在其他文件中用break命令设置断点呢?我们看这个例子:

把3.1的代码分为三个py文件,放下同一路径下:

  ![在这里插入图片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4b5d476ba5b14b0ba541d78930b9704a~tplv-k3u1fbpfcp-zoom-1.image)

看一下每个文件的内容:

run.py:

初始的 pdb.set_trace() 设置在run.py中。

import torchfrom encoder import Encoderimport pdbif __name__=="__main__":    pdb.set_trace()    input = torch.rand(5, 4, 30, 30)    model = Encoder(num_layers=4)    output = model(input)

encoder.py:

from encoder_layer import EncoderLayerimport torch.nn as nnclass Encoder(nn.Module):    def __init__(self,num_layers):        super().__init__()        # encoders 由 num_layers个 EncoderLayer子层组成,每个子层结构相同,但参数不一定相同。        self.ModelList = nn.ModuleList([EncoderLayer() for _ in range(num_layers)])    def forward(self, x):        # ModuleList是一个list,只能通过list的操作方式(如用for循环、下标索引等)进行forward计算。        for layer in self.ModelList:            x = layer(x)        return x

encoder_layer.py:

import torch.nn as nnclass EncoderLayer(nn.Module):    def __init__(self):        super().__init__()        self.conv1 = nn.Conv2d(4, 10, (3, 3))        self.conv2 = nn.Conv2d(10, 4, (3, 3))        self.relu = nn.ReLU()    def forward(self, x):        x=self.relu(self.conv1(x))        return self.relu(self.conv2(x))

现在我们运行 run.py ,然后在 encoder.py 的第12行 设置断点,即

for layer in self.ModelList:

命令为:

break encoder.py:12

即 break filename:linepython调试工具pdb怎么使用我们可以看到,程序可以从  output = model(input) 进入到 forward() 中:python调试工具pdb怎么使用这样可以很方便地进行调试。

如果初始断点与目标断点不在同一个目录下的文件中,也可以通过相对路径下的文件名设置断点,如:

(Pdb) break ../transfORMer/asr_model.py:91Breakpoint 1 at /local/wenet/examples/aishell/s0/wenet/transformer/asr_model.py:91(Pdb)

四、使用 pdb 时发现的问题

4.1 使用软链接时,pdb 显示的文件路径与实际路径不一致的问题

如图可以发现,pdb 有三行组成,第一行时文件路径,第二行是当前执行的代码行,第三行是输入命令行。

在存在软链接时,pdb显示的路径是软链接指向的路径,但实际上的代码路径是拷贝了软连接内容的路径,这两个路径不一样,一定要注意。python调试工具pdb怎么使用

4.2 pdb有时候无法在模型的 forward() 方法中加入断点

pdb有时候无法用 pdb.set_trace() 在模型的 forward() 方法中加入断点,报错内容为:

Compiled functions can't take variable number of arguments or use keyWord-only arguments with defaul

大概意思是 “编译后的函数不能接受数量可变的参数,也不能在default中使用仅关键字参数。”

不懂啥意思,这个问题也没有解决。

五、程序奔溃后的事后调试:pdb.pm()

前面所述都是在程序开始运行时就插入断点,用pdb进行调试,即事前调试。其实 pdb 还可以进行事后调试,即在程序有bug运行奔溃后用python调试器进行查看。

比如 test.py 显然是有 bug 的:

# test.pydef add(n):    return n+1add("hello")

直接运行:

python test.py

程序奔溃:

F:\PyCharmProjects\PyTorch_practice>python test.pyTraceback (most recent call last):  File "test.py", line 4, in <module>    add("hello")  File "test.py", line 2, in add    return n+1TypeError: can only concatenate str (not "int") to str

这样我们是无法用pdb进行调试的。那么当程序崩溃后,我们该怎样去调试呢?

我们可以用下面这个命令进行简单调试:

python -i test.py

-i 选项可以让程序结束后打开一个交互式shell,如下:

F:\PycharmProjects\pytorch_practice>python -i test.pyTraceback (most recent call last):  File "test.py", line 4, in <module>    add("hello")  File "test.py", line 2, in add    return n+1TypeError: can only concatenate str (not "int") to str>>>

现在我们发现程序结束后出现了 >>> 符号,这就是python调试器。

输入命令:

import pdbpdb.pm()

其中 pdb.pm() 用于程序发生异常导致奔溃后的事后调试,可以跟踪异常程序最后的堆在信息。

执行命令后得到:

TypeError: can only concatenate str (not "int") to str>>> import pdb>>> pdb.pm()> f:\pycharmprojects\pytorch_practice\test.py(2)add()-> return n+1(Pdb)

可以发现,pdb.pm() 已经追踪到了导致程序奔溃的语句:return n+1

此时可以打印 n 的值进行检查:

(Pdb) p n'hello'(Pdb) q>>> quit()F:\PycharmProjects\pytorch_practice>

q 表示退出pdb调试,quit() 表示退出 python 调试器。

感谢各位的阅读,以上就是“python调试工具pdb怎么使用”的内容了,经过本文的学习后,相信大家对python调试工具pdb怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: python调试工具pdb怎么使用

本文链接: https://www.lsjlt.com/news/345389.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作