Python 网络爬虫实战
上QQ阅读APP看书,第一时间看更新

2.5 Python调试

调试是Python编程中非常重要的一环。程序出现什么问题,查看抛出的异常。或者处处加print和log找出错误点,再慢慢地反推,是可以找到问题解决问题的。但是有更简单的方法为什么非得舍易取难呢?

在Linux和Windows平台有很多的第三方调试工具,一般的Python IDE基本也自带了调试工具。工具太多了反而不好选择,而且也不是随手都能找到第三方调试工具的。这里仅示范手头上必定有的,Python自带的调试工具。其他的第三方调试工具都大同小异,熟悉了最简单的,其他的也就无师自通了。

2.5.1 Windows下IDLE调试

先写个简单的程序来做示例。既然是调试,最好的选择莫过于多次调用函数的阶乘了,这个程序简单又明显,适合用来做示例。打开IDLE,单击菜单栏的File|New File。创建一个新文档。编辑代码如图2-22所示。

图2-22 testWinDebugFactorial.py

单击菜单栏File|Save As,选择保存位置后将文件保存为testWinDebugFactorial.py。下面开始调试testWinDebugFactorial.py。

单击IDLE菜单栏的Run|Python Shell,打开Python Shell,如图2-23所示。

图2-23 打开Python Shell

单击Python Shell菜单栏的Debug|Debugger。打开Debug Control窗口,如图2-24所示。

图2-24 打开Debug Control

然后在IDLE窗口为代码添加断点。所谓断点简单地说就是调试程序时需要停顿的位置。一般在函数的入口、参数变化的行添加。这里只在fac函数入口添加一个断点。单击fac函数入口行,再右击弹出菜单,选择Set Breakpoing,如图2-25所示。

图2-25 设置断点

现在可以开始运行调试程序了,单击IDLE窗口菜单栏的Run|Run Module,如图2-26所示。

图2-26 运行调试程序

单击Debug Control窗口的Go按钮,开始运行程序,然后单击Debug Control窗口的Step按钮,逐步运行程序。如果需跳出循环或者跳出函数,则单击Debug Control窗口的Out按钮。Debug Control窗口中的Stack检查框显示的是程序当前运行位置,Locals检查框显示的是当前变量的值,如图2-27所示。

图2-27 Debug Control

通过Debug调试很容易发现程序中的错误之处。虽然这个Debug工具比较简陋,但基本功能都还齐全,算是比较好用的一款Debug工具了。

2.5.2 Linux下pdb调试

Linux下Python调试工具也很多,但最简单、最方便的可能就是pdb了。pdb功能齐全,使用方便,使用过gdb的朋友会对它非常熟悉,它们的命令几乎是一模一样的。先写个示范程序,用pdb调试一下。

【示例2-16】打开Putty连接到Linux,执行命令:

        cd code/crawler
        vi testLinuxBugListExtremum.py

testLinuxBugListExtremum.py的代码如下:

          1 #! /usr/bin/env python
          2 #-*- coding: utf-8-*-
          3 __author__ = 'hstking hstking@hotmail.com'
          4
          5 import cls
          6 import time
          7
          8 def getList():
          9     #构建一个纯数字列表
          10      numList = []
          11      num = 'q'
          12      while num:
          13           cls.clear()
          14           print numList
          15          print(u’结束构建列表,请按回车’)
          16          num = raw_input(’请输入一个整数:')
          17           if num == '':
          18                break
          19           try:
          20                num = int(num)
          21           except ValueError:
          22              print(u’要求输入整数,请重新输入’)
          23                time.sleep(1)
          24                continue
          25           numList.append(num)
          26      return numList
          27
          28 def getMaxNum(List):
          29     #获取列表中最大值
          30      num = List[0]
          31      for i in List[1:]:
          32           if num <= i:
          33                num = i
          34      return num
          35
          36 def getMinNum(List):
          37     #获取列表中最小值
          38      num = List[0]
          39      for i in List[1:]:
          40           if num >= i:
          41                num = i
          42      return num
          43
          44
          45 if __name__ == '__main__':
          46      numList = getList()
          47      maxNum = getMaxNum(numList)
          48     print(u’列表中最大值为:%d' %maxNum)
          49      minNum = getMinNum(numList)
          50     print(u’列表中最小值为:%d' %minNum)

testLinuxBugListExtremum.py程序让用户输入一组整数放入列表中,然后从列表中挑选出最大值和最小值。以testLinuxBugListExtremum.py为例,使用pdb调试。

下面先简单地介绍一下pdb。pdb在Python中是以模块的形式出现的,它是Python的标准库。可以在Python交互环境中使用,如图2-28所示。

图2-28 模块式使用pdb

也可以在程序中间插入一段程序,相当于在一般IDE里面打上断点,然后启动debug,不过这种方式是hardcode的,如图2-29所示。

图2-29 程序内使用pdb

将pdb放入程序内,在运行程序时。运行到pdb行后就暂停了,然后开始运行pdb程序。这种方式需要改动程序,还是比较麻烦。

笔者更喜欢最后一种方法,命令行启动目标程序,加上-m参数调用pdb模块,如图2-30所示。

图2-30 命令调用pdb模块

图2-20显示了pdb的所有命令,这里只说明最常用的几个:

● list:显示程序,可以带参数。比如显示第5行list 5。

● break:添加断点。比如在第5行添加断点break 5,在getList函数添加断点break。

● run:开始运行程序。

● step:单步运行,进入函数内部。

● next:单步运行,不进入函数内部。

● print:显示参数。

● quit:退出pdb。

下面开始调试testLinuxBugListExtremum.py程序。执行命令:

        python -m pdb testLinuxBugListExtremum.py
        list 52
        break getList
        break getMaxNum
        break getMinNum
        break

执行结果如图2-31所示。

图2-31 pdb加入断点

执行命令run,开始运行程序,函数外的行使用next单步运行,到了函数入口后使用step单步运行。中途使用print命令随时监视变量变化,如图2-32所示。

图2-32 调试testLinuxDebugListExtremum.py

调试完毕后输入quit,退出pdb。pdb没有GUI,用起来似乎没有那么直观。用习惯了也还挺方便的。如果偏爱GUI,那还是找个Python IDE吧,Eclipse + pydev就很方便了。也是多平台通用,除了块头大一点,没什么缺点。

注意:pdb是Python调试工具,它也是Python的标准模块之一,所以也可以用import将它导入到程序中使用。