• 热门专题

python调试第一战—PDB

作者:雷霆万钧  发布日期:2011-08-22 19:48:52
Tag标签:python  调试  第一战  PDB  
  • 今天花了点时间看了一下Python自带的pdb库,发现用pdb来调试程序还是很方便的,当然了,什么远程调试,多线程之类,pdb是搞不定的。

    用pdb调试有多种方式可选:

    1. 命令行启动目标程序,加上-m参数,这样调用myscript.py的话断点就是程序的执行第一行之前
    python -m pdb myscript.py

    2. 在Python交互环境中启用调试
    >>> import pdb
    >>> import mymodule
    >>> pdb.run(‘mymodule.test()’)

    3. 比较常用的,就是在程序中间插入一段程序,相对于在一般IDE里面打上断点然后启动debug,不过这种方式是hardcode的

     

    if __name__ == "__main__":
        a = 1
        import pdb
        pdb.set_trace()
        b = 2
        c = a + b
        print (c)

     

    然后正常运行脚本,到了pdb.set_trace()那就会定下来,就可以看到调试的提示符(Pdb)了

    常用的调试命令

    h(elp),会打印当前版本Pdb可用的命令,如果要查询某个命令,可以输入 h [command],例如:“h l” — 查看list命令
    l(ist),可以列出当前将要运行的代码块
    (Pdb) l
    497 pdb.set_trace()
    498 base_data = {}
    499 new_data = {}
    500 try:
    501 execfile(base_file_name,{},base_data)
    502 -> execfile(new_file_name,{},new_data)
    503 except:
    504 logger.writeLog(“error! load result log error!”)
    505 print “load cmp logs error!”
    506 raise Exception, “load cmp logs error!”
    507

    b(reak), 设置断点,例如 “b 77″,就是在当前脚本的77行打上断点,还能输入函数名作为参数,断点就打到具体的函数入口,如果只敲b,会显示现有的全部断点
    (Pdb) b 504
    Breakpoint 4 at /home/jchen/regression/regressionLogCMP.py:504

    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),如果后面带有参数,就是清除指定的断点(我在Python2.4上从来没成功过!!!);如果不带参数就是清除所有的断点
    (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),退出调试
    发现在命令行下调试程序也是一件挺有意思的事情,接下来分享一个测试用例,由于python的单元测试与java的junit是同一作者,所以学过junit的同学应该很熟悉了:


    下面是一个简单的数学库,实现了简单的加减函数。代码如下:

    1 def add(op1, op2):

    2     return op1+op2;

    3  

    4 def sub(op1, op2):

    5     return op1-op2;

    主程序会调用数学库中的函数,代码如下:

    01 #!/usr/bin/env python

    02  

    03 import math_utils

    04  

    05 a = 3;

    06 b = 4;

    07  

    08 c = math_utils.add(a, b);

    09  

    10 print c;

    下面演示了几条最基本的调试命令的使用方法,包括”list”,”continue”,”break”,”run”,”backtrace”等等。打断点的时候不要打在函数的def处。如果这样做,import的时候会运行到这个位置,真正调用函数时却不会停住。impor的时候会生成Python内部的运行指令,因此会运行到每个函数定义的地方。

    01 henshao@henshao-desktop:~/source$ python -m pdb main.py

    02 > /home/henshao/source/main.py(3)<module>()

    03 -> import math_utils

    04 (Pdb) h

    05  

    06 Documented commands (type help <topic>):

    07 ========================================

    08 EOF    bt         cont      enable  jump  pp       run      unt

    09 a      c          continue  exit    l     q        s        until

    10 alias  cl         d         h       list  quit     step     up

    11 args   clear      debug     help    n     r        tbreak   w

    12 b      commands   disable   ignore  next  restart  u        whatis

    13 break  condition  down      j       p     return   unalias  where

    14  

    15 Miscellaneous help topics:

    16 ==========================

    17 exec  pdb

    18  

    19 Undocumented commands:

    20 ======================

    21 retval  rv

    22  

    23 (Pdb) b math_utils.py:4

    24 Breakpoint 1 at /home/henshao/source/math_utils.py:4

    25 (Pdb) h cont

    26 c(ont(inue))

    27 Continue execution, only stop when a breakpoint is encountered.

    28 (Pdb) run

    29 Restarting main.py with arguments:

    30  

    31 > /home/henshao/source/main.py(3)<module>()

    32 -> import math_utils

    33 (Pdb) cont

    34 > /home/henshao/source/math_utils.py(4)add()

    35 -> return op1+op2;

    36 (Pdb) bt

    37   /usr/lib/python2.6/bdb.py(368)run()

    38 -> exec cmd in globals, locals

    39   <string>(1)<module>()

    40   /home/henshao/source/main.py(8)<module>()

    41 -> c = math_utils.add(a, b);

    42 > /home/henshao/source/math_utils.py(4)add()

    43 -> return op1+op2;

    44 (Pdb) args

    45 op1 = 3

    46 op2 = 4

    Python的单元测试框架同JUnit差不多,因为它们的开发者都是Kent Beck,接口都是一样的。使用setUp和tearDown做准备和收尾工作。每个要测试的接口都以”test”开始。在math_utils.py添加下面这段代码便可。

    01 import unittest

    02  

    03 class MathTestCase(unittest.TestCase):

    04         def setUp(self):

    05                 pass;

    06  

    07         def tearDown(self):

    08                 pass;

    09  

    10         def testAdd(self):

    11                 self.assertEqual(add(4, 5), 9)

    12  

    13         def testSub(self):

    14                 self.assertEqual(sub(8, 5), 3);

    15  

    16         def suite():

    17                 suite = unittest.TestSuite()

    18                 suite.addTest(MathTestCase())

    19                 return suite

    20  

    21 if __name__ == "__main__":

    22         unittest.main()

    直接运行程序,得到以下输出:

    1 henshao@henshao-desktop:~/source$ python math_utils.py

    2 ..

    3 ----------------------------------------------------------------------

    4 Ran 2 tests in 0.000s

    5  

    6 OK

    上面这种方式将测试代码同源代码混杂在一起,并不是一种很好的方式。可以将测试用例的代码放到一个单独的unittest目录中。对每个用例设计一个test case,然后使用下面这种方式添加测试用例。

    view source print?1 if __name__ == "__main__":

    2         suite = unittest.TestSuite()

    3  

    4         suite.addTest(MathTestCase("testAdd"))

    5         suite.addTest(MathTestCase("testSub"))

    6  

    7         runner = unittest.TextTestRunner()

    8         runner.run(suite)

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规