如何逐步执行 Python 代码来帮助调试问题?
- 2024-11-22 08:48:00
- admin 原创
- 236
问题描述:
在 Java/C# 中,您可以轻松地逐步执行代码来追踪可能出现的问题,而且 IDE 使这个过程非常用户友好。
您能以类似的方式追踪 Python 代码吗?
解决方案 1:
是的!有一个 Python 调试器就是pdb
为此而调用的!
pdb
您可以通过via启动 Python 程序python -m pdb myscript.py
。
然后您可以发出一些命令,这些命令记录在pdb
页面上。
需要记住的一些有用的内容是:
b
:设置断点c
:继续调试,直到到达断点s
:逐步执行代码n
:转到下一行代码l
:列出当前文件的源代码(默认值:包括正在执行的行在内的 11 行)u
:向上导航堆栈框架d
:向下导航堆栈框架p
:打印当前上下文中表达式的值
如果您不想使用命令行调试器,某些 IDE(如Pydev、Wing IDE或PyCharm)具有 GUI 调试器。Wing 和 PyCharm 都是商业产品,但 Wing 有免费的“个人”版本,而 PyCharm 有免费的社区版本。
解决方案 2:
使用 Python 交互式调试器“pdb”
第一步是让 Python 解释器进入调试模式。
A. 从命令行
最直接的方式,从命令行运行 Python 解释器
$ python -m pdb scriptName.py
> .../pdb_script.py(7)<module>()
-> """
(Pdb)
B. 在解释器中
在开发模块的早期版本时,并进行更迭代的实验。
$ python
Python 2.7 (r27:82508, Jul 3 2010, 21:12:11)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb_script
>>> import pdb
>>> pdb.run('pdb_script.MyObj(5).go()')
> <string>(1)<module>()
(Pdb)
C. 从你的程序内部
import pdb
对于大型项目和长期运行的模块,可以使用如下方法从程序内部启动调试set_trace()
:
#!/usr/bin/env python
# encoding: utf-8
#
import pdb
class MyObj(object):
count = 5
def __init__(self):
self.count= 9
def go(self):
for i in range(self.count):
pdb.set_trace()
print i
return
if __name__ == '__main__':
MyObj(5).go()
逐步调试以深入内部
用“n”(下一个)执行下一个语句…
重复上一个调试命令…按ENTER
退出一切……用“q”(退出)
使用“p”(打印)打印变量的值...
一个) p a
使用“c”关闭(Pdb)提示符(继续)
使用“l”(列表)查看您所在的位置
进入子程序…用“s”(进入)
继续…但只到当前子程序的结尾…用“r”(返回)
分配新值
一个) !b = "B"
设置断点
一个) break linenumber
b) break functionname
c) break filename:linenumber
临时断点
一个) tbreak linenumber
条件断点
一个) break linenumber, condition
注意:所有这些命令都应该从pdb执行
如需深入了解,请参阅:
解决方案 3:
Python 中有一个名为“pdb”的模块。在 Python 脚本的顶部,您可以执行
import pdb
pdb.set_trace()
然后您将进入调试模式。您可以使用“s”来逐步执行,使用“n”来跟踪下一行,类似于使用“gdb”调试器的操作。
解决方案 4:
从 Python 3.7 开始,你可以使用breakpoint()
内置函数进入调试器:
foo()
breakpoint() # drop into the debugger at this point
bar()
默认情况下,breakpoint()
将导入pdb
并调用。但是,您可以通过环境变量的使用pdb.set_trace()
来控制调试行为。sys.breakpointhook()
`PYTHONBREAKPOINT`
有关更多信息,请参阅PEP 553 。
解决方案 5:
ipdb(IPython 调试器)
ipdb为 pdb 添加了 IPython 功能,提供了以下巨大的改进:
Tab 补全
显示更多上下文行
语法高亮
与 pdg 类似,与 GDB 相比,ipdb 仍然远非完美且完全不成熟,但它已经比 pdb 有了很大的改进。
使用方法与类似pdb
,只需使用以下命令安装:
python3 -m pip install --user ipdb
然后添加到您想要进行单步调试的行:
__import__('ipdb').set_trace(context=21)
您可能希望从编辑器中添加一个快捷方式,例如对于Vim snipmate,我有:
snippet ipd
__import__('ipdb').set_trace(context=21)
因此我只需输入即可ipd<tab>
,它会扩展到断点。然后删除它很容易,dd
因为所有内容都包含在一行中。
context=21
增加上下文行数,如以下解释:如何让 ipdb 在调试时显示更多上下文行?
或者,您也可以从一开始就调试程序:
ipdb3 main.py
但你通常不想这样做,因为:
你必须仔细检查所有的函数和类定义,因为 Python 会读取这些行
我不知道如何在不破解 ipdb 的情况下在那里设置上下文大小。允许它的补丁:https ://github.com/gotcha/ipdb/pull/155
或者,像在 raw pdb 3.2+ 中一样,您可以从命令行设置一些断点:
ipdb3 -c 'b 12' -c 'b myfunc' ~/test/a.py
虽然-c c
由于某种原因被破坏了: https: //github.com/gotcha/ipdb/issues/156
python -m module
调试已在以下位置询问:如何从命令行调试使用 python -m 运行的 Python 模块?并且从 Python 3.7 开始可以使用以下方法完成:
python -m pdb -m my_module
与 GDB 相比,pdb 和 ipdb 都缺少以下严重功能:
跨会话持久保存命令历史记录:将命令历史记录保存在 pdb 中
ipdb 特定的烦恼:
如果您不修改某些设置,多线程就无法正常工作......
+ ipdb、多线程和自动重新加载程序导致 ProgrammingError
+ https://github.com/gotcha/ipdb/issues/51
在 Ubuntu 16.04、ipdb==0.11、Python 3.5.2 中测试。
解决方案 6:
VSCode
如果您想使用 IDE,这是 PyCharm 的一个很好的替代品。
安装VSCode
如果尚未安装,请安装Python 扩展
例如,创建一个
mymodule.py
包含 Python 代码的文件要设置断点,请将鼠标悬停在行号上并单击红点,或按
F9
点击
F5
开始调试并选择Python文件
它将在断点处停止,您可以执行常规调试操作,例如检查变量的值,可以在“变量”选项卡(通常在左侧)或单击“调试控制台” (通常在终端旁边的底部)进行:
此截图显示的是VSCodium。
更多信息
VS Code 中的 Python 调试
在 VS Code 中开始使用 Python
在 Visual Studio Code 中调试
解决方案 7:
现在存在breakpoint()
一种方法,可以替代import pdb; pdb.set_trace()
。
它还具有一些新功能,例如可能的环境变量。
解决方案 8:
让我们看看breakpoint()
3.7+ 能为您做什么。
我已经安装了ipdb和pdbpp,它们都是增强型调试器,通过
pip install pdbpp
pip install ipdb
我的测试脚本实际上并没有做太多事情,只是调用breakpoint()
。
#test_188_breakpoint.py
myvars=dict(foo="bar")
print("before breakpoint()")
扫码咨询,免费领取项目管理大礼包!