Python调试-logging 和 pdb 的使用

王 茂南 2018年11月10日22:49:37
评论
2992字阅读9分58秒
摘要这一篇文章简单介绍两种Python调试的方法,希望可以提高Python调试的效率,也方便自己之后的查找。

简介

这一篇文章主要介绍一些 Python 的两个调试方法,使用 pdb(或是 ipdb)logging 这两种方式进行调试。关于 logging 模块更加详细的使用,可以参考链接,Python 的 logging 模块的使用

关于 pdb 的内容,部分参考自以下的链接,【python】来学学debugger吧,不能只会用print调试呀!

 

logging

之前自己调试的时候其实经常会使用 print 来进行调试,但是最后使用的时候会打印很多信息。通常情况下,当调试完毕之后就不想打印这么多了,这个时候可以使用 logging 来进行调试。

关于详细资料可以查看这个链接(这里有非常详细的使用方式)Python 的 logging 模块的使用

下面大致看一下如何使用 logging 模块。使用 logging 需要在最开始添加一行配置,如下所示

  1. import logging
  2. logging.basicConfig(level=logging.INFO)

logging 允许你指定记录信息的级别,有debuginfowarningerror等几个级别。当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debuginfo就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。

logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。(来自廖雪峰Python3-调试

我们看一个例子,来大致了解一下:

  1. import fire
  2. import pdb
  3. import logging
  4. logging.basicConfig(level=logging.INFO)
  5. def Multiplication(x, y):
  6.     """
  7.     x*y
  8.     """
  9.     logging.info("To Calcuate %d * %d" % (x,y))
  10.     logging.info("--- --- ---")
  11.     z=x*y
  12.     #pdb.set_trace()
  13.     return(z)
  14. def main():
  15.     fire.Fire(Multiplication)
  16. if __name__ == '__main__':
  17.     main()

我们看一下运行的效果,这样调试信息会直接输出出来;

Python调试-logging 和 pdb 的使用

我们也可以将logging输出到文件中,只需要修改第一行的配置;

  1. logging.basicConfig(filename='logger.log',level=logging.INFO)
Python调试-logging 和 pdb 的使用

 

使用 pdb 进行调试

设置断点

pdb 是 python 自带的一种调试方式。这种方法可以设置断点,进行单步调试,查看栈内变量。使用 pdb 最简单的方式就是在代码中加入 breakpoint() 即可。然后代码就会停在指定的位置。(或是使用 pdb.set_trace 也是可以的)

有的时候我们无法直接对原始文件进行修改,也可以使用命令行的方式启动调试:

  1. python -m pdb xxx.py

运行上面的代码之后,他会在第一个可以停下来的地方就停下来。

 

pdb 监视当前程序状态

我们可以使用 pdb 很方便的检视当前程序的状态,下面是一些常用的命令:

  • w:查看代码的堆栈调用(这里 > 表示我们当前在什么 frame);
  • u:使用 u 或是 up 跳转到上一个 frame;
  • d:使用 d 或是 down 跳转到下一个 frame;
  • l:查看当前断点附近的代码;
  • ll:显示当前函数的全部代码;

下图中我们展示了当前所在的堆栈,可以看到:

  • 第一次使用 w 查看的时候在 read_config 函数里面;
  • 之后可以 u 返回上面一层 frame;
  • 最后再次使用 w 查看的时候可以看到返回了调用 read_config 处的代码;
Python调试-logging 和 pdb 的使用

 

pdb 控制程序运行

上面我们使用 breakpoint()让程序停在了想要的位置,同时查看了程序的信息。接着我们可以使用 pdb 来控制程序的运行。下面展示一些常用的操作:

Python调试-logging 和 pdb 的使用

下面是一些常用的控制程序运行的代码。

  1. (Pdb)n #单步运行
  2. (Pdb)s #细点运行,进入到某个函数里面,也就是 step
  3. (Pdb)c #跳到下个断点

总结一下,我们可以分别使用:

  • n:单步调试程序,但是遇到函数会直接运行结束;
  • s:与上面 n 不同的是,在遇到函数时候,会进入函数内部运行;
  • until:运行直到行数比现在的行数大为止(可以用于跳出循环或函数);
    • until xx:这个命令可以带有参数,until 10 就是表示运行到第 10 行(不能在不同函数之间跳转);
  • r:使用 r 或是 return 停在函数 return 之前;
  • c:使用 c 或是 continue 来继续程序直到结束;
  • b:设置断点,和 breakpoint 等价,例如 b 5 就是表示在当前文件的第五行设置断点;
    • b 后面什么都不加,就是列出所有的断点;
    • b function_name 可以停在指定的函数里面(我们需要确保此时这个函数已经被 import 进来了,可以使用 b 行数,直接跳转到 import 之后,然后在函数里面打断点);
    • b 文件路径/文件名:行数,可以在指定文件的指定行数进行断点,例如 b ../utils/readConfig.py:7 表示在文件的第七行设置断点,这里的路径是与当前文件相对的路径;
  •  clear:用于删除断点,clear id 删除指定的断点;

 

pdb 命令合集

下面是我在网上找到的一个 pdb 的命令合集。少了使用 w 查看当前堆栈,使用 ud 对堆栈进行改变。使用 until 运行到某行。

Python调试-logging 和 pdb 的使用

 

使用 ipdb 进行调试

ipdb 可以看作是上面 pdb 的升级版,需要进行安装。使用pip install ipdb即可轻松安装。在使用的时候,有两种方式,分别是「集成到源代码中」和「命令式」,我们分别来看例子。

ipdb 使用方式--集成到源代码中

我们可以在代码指定的位置插入断点,从而进行调试。下面我们看一个例子。

  1. def add_x_y(x, y):
  2.     import ipdb; ipdb.set_trace() # 打断点
  3.     return x+y
  4. if __name__ == "__main__":
  5.     x1 = 1
  6.     y1 = 2
  7.     result = add_x_y(x1, y1)

我们运行这个代码,程序会在进入函数 add_x_y 后停止,展开 Ipython 环境,就可以自由地调试了。例如我们可以通过 a 查看输入函数的所有参数:

Python调试-logging 和 pdb 的使用

 

ipdb 使用方式--命令式

除了上面的方式外,我们还可以使用以下的命令按步执行,边运行边跟踪代码进行调试。下面的方法可以启动 ipdb 的调试环境:

  1. python -m ipdb your_code.py

首先我们通过上面的命令进入 ipdb 的调试环境:

Python调试-logging 和 pdb 的使用

接着我们可以通过一些常见的命令进行调试。下面是一些常见的命令:

  • h,调出 ipdb 的帮助文档;
  • b,打断点,使用 b line_number(break) 的方式给指定的行号位置加上断点。使用 b file_name:line_number 的方法给指定的文件(还没执行到的代码可能在外部文件中)中指定行号位置打上断点;
  • n(next),执行下一个语句(不会进入函数内部);
  • s(step into),进入函数内部进行调试;
  • c(continue),执行代码,直到遇到下一个断点;
  • w(where),查看自己在哪里;
  • q,退出调试;

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南
  • 本文由 发表于 2018年11月10日22:49:37
  • 转载请务必保留本文链接:https://mathpretty.com/9849.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: