Python中Debug有很多种方式,比如直接用ide去 pydebug,或者命令行去debug。这里介绍Python调试代码的4种方法:print、log、pdb、PyCharm的debug,分别有什么优缺点。
一.使用ide debug
PyCharm提供的debug功能,也提供了单步调试代码的功能。
优点:提供图形化界面,很直观;功能强大;不需要修改代码
缺点:依赖ide
二. print
用print调试代码是最简单的一种方法,也很常用,大部分人都掌握这种技巧。
在代码中合适的地方插入语句,可以是输出提示语句或者输出某些变量。
优点:比较直观,使用简单
缺点:需要入侵代码,也就是要修改代码
三. logging
就是利用logging模块,在代码合适的地方插入输出log语句,把合适的信息输出到log文件中,通过查看log文件分析代码的执行情况。
优点:logging模块可以指定输出格式和内容(可以输出时间,代码的行号,当前运行程序的名称、当前运行的函数名称、进程ID等等),因此能获得更精确的调试信息,应用场景更广泛,可以应用于生产环境。
缺点:需要入侵代码,也就是要修改代码;使用更复杂。
import os
import time
import logging
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
log_dir = os.path.join(root_dir, "logs")
if not os.path.exists(log_dir):
os.mkdir(log_dir)
my_logging = logging.getLogger('bktest') # 创建日志收集器
my_logging.setLevel('DEBUG') # 设置日志收集级别
ch = logging.StreamHandler() # 输出到控制台
# my_logging.setLevel('INFO') # 设置日志输出级别
my_logging.addHandler(ch) # 对接,添加渠道
# 创建文件处理器fh,log_file为日志存放的文件夹
log_file = os.path.join(log_dir, "{}_log".format(time.strftime("%Y-%m-%d", time.localtime())))
fh = logging.FileHandler(log_file, encoding="UTF-8")
my_logging.addHandler(fh) # 对接,添加渠道
# 指定输出的格式
formatter = logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-%(name)s-日志信息-%(message)s')
# 规定日志输出的时候按照formatter格式来打印
ch.setFormatter(formatter)
fh.setFormatter(formatter)
my_logging.debug("这是一个debug的信息")
my_logging.info("这是一个info的信息")
my_logging.warning("这是一个warning的信息")
my_logging.error("这是一个error的信息")
my_logging.critical("这是一个critical的信息")
s = list()
for i in range(10):
my_logging.debug("test")
s.append(i)
print(s)
四. pdb
debug是编码是非常重要的调试技巧,通过在运行过程中设置断点,帮助开发人员更好的理解运行过程。
Python中debug不像JAVA或者C++那样在IDE中设置断点那么直观。
下面记录一下另外一种方式,直接以命令行的方式debug:
pdb 是 python 自带的一个包,为 python 程序提供了一种交互的源代码调试功能,主要特性包括设置断点、单步调试、进入函数调试、查看当前代码、查看栈片段、动态改变变量的值等。
优点:功能强大,使用简单
缺点:需要入侵代码,也就是要修改代码;使用更复杂。
方式一:在命令行中运行
python -m pdb my_script.py
方式二:脚本中运行
在需要设置断点的地方,插入方法 pdb.set_trace()
import ipdb as pdb
s = list()
for i in range(10):
pdb.set_trace()
s.append(i)
print(s)
命令: 在进入调试状态之后,就可以输入命令进行调试了。
c: (continue)继续执行
w:(words)显示当前行的上下文信息
a:(arguments)打印当前函数的参数列表
s:(stop)执行当前行,并在顶一个可能的时机停止
n:(next)继续执行直到当前函数的下一行或者函数返回值
通过h可以看到更多的命令,根据需要使用就好了
ipdb> h
Documented commands (type help <topic>):
========================================
EOF commands enable ll pp s until
a condition exit longlist psource skip_hidden up
alias cont h n q skip_predicates w
args context help next quit source whatis
b continue ignore p r step where
break d interact pdef restart tbreak
bt debug j pdoc return u
c disable jump pfile retval unalias
cl display l pinfo run undisplay
clear down list pinfo2 rv unt
Miscellaneous help topics:
==========================
exec pdb
关于pdb的一些常用命令:
常用的调试命令
h(elp),会打印当前版本Pdb可用的命令,如果要查询某个命令,可以输入 h [command],例如:“h l” — 查看list命令
l(ist),可以列出当前将要运行的代码块
(Pdb) l
b(reak), 设置断点,例如 “b 77″,就是在当前脚本的77行打上断点,还能输入函数名作为参数,断点就打到具体的函数入口,如果只敲b,会显示现有的全部断点
condition bpnumber [condition],设置条件断点,下面语句就是对第4个断点加上条件“a==3”
(Pdb) condition 4 a==3
(Pdb) b
Num Type Disp Enb Where
4 breakpoint keep yes at /home/jchen/regression/regressionLogCMP.py:504
stop only if a==3
cl(ear),如果后面带有参数,就是清除指定的断点;如果不带参数就是清除所有的断点
(Pdb) cl
Clear all breaks? y
disable/enable,禁用/激活断点
(Pdb) disable 3
(Pdb) b
Num Type Disp Enb Where
3 breakpoint keep no at /home/jchen/regression/regressionLogCMP.py:505
n(ext),让程序运行下一行,如果当前语句有一个函数调用,用n是不会进入被调用的函数体中的
s(tep),跟n相似,但是如果当前有一个函数调用,那么s会进入被调用的函数体中
c(ont(inue)),让程序正常运行,直到遇到断点
j(ump),让程序跳转到指定的行数
(Pdb) j 497
> /home/jchen/regression/regressionLogCMP.py(497)compareLog()
> -> pdb.set_trace()
a(rgs),打印当前函数的参数
(Pdb) a
_logger =
_base = ./base/MRM-8137.log
_new = ./new/MRM-8137.log
_caseid = 5550001
_toStepNum = 10
_cmpMap = {‘_bcmpbinarylog’: ‘True’, ‘_bcmpLog’: ‘True’, ‘_bcmpresp’: ‘True’}
p,最有用的命令之一,打印某个变量
(Pdb) p _new
u’./new/MRM-8137.log’
!,感叹号后面跟着语句,可以直接改变某个变量
q(uit),退出调试
发现在命令行下调试程序也是一件挺有意思的事情,记录下来分享一下
w ,Print a stack trace, with the most recent frame at the bottom.An arrow indicates the "current frame",
which determines the context of most commands. 'bt' is an alias for this command.
d ,Move the current frame one level down in the stack trace
(to a newer frame).
u ,Move the current frame one level up in the stack trace
(to an older frame).
使用 u 和 d 命令,我们可以在栈帧之间切换,用以获取其相关上下文变量信息。w可以显示最近的一些栈帧信息。
常用的 pdb debug 命令:
命令 用途
- break 或 b 设置断点
- continue 或 c 继续执行程序, 或是跳到下个断点
- list 或 l 查看当前行的代码段
- step 或 s 进入函数
- return 或 r 执行代码直到从当前函数返回
- exit 或 q 中止并退出
- next 或 n 执行下一行
- p 或! 打印变量的值,例如p a
- help 或 h 帮助
其他
pdb调试命令
完整命令 简写命令 描述
- args a 打印当前函数的参数
- break b 设置断点
- clear cl 清除断点
- condition 无 设置条件断点
- continue c或者cont 继续运行,知道遇到断点或者脚本结束
- disable 无 禁用断点
- enable 无 启用断点
- help h 查看pdb帮助
- ignore 无 忽略断点
- jump j 跳转到指定行数运行
- list l 列出脚本清单
- next n 执行下条语句,遇到函数不进入其内部
- p p 打印变量值,也可以用print
- quit q 退出 pdb
- return r 一直运行到函数返回
- tbreak 无 设置临时断点,断点只中断一次
- step s 执行下一条语句,遇到函数进入其内部
- where w 查看所在的位置
- ! 无 在pdb中执行语句
- Post link: https://yanxiang.wang/Python4%E7%A7%8DDebug%E6%96%B9%E6%B3%95/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.