免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 31438 | 回复: 12

Python调试技巧介绍 [复制链接]

论坛徽章:
0
发表于 2008-08-30 01:42 |显示全部楼层
Python调试技巧

鉴于这个问题已经被问过多次了,我觉得应该写一个文档介绍一下Python的调试。

1. print
不要看不起print,这是一切调试的起点,即便是调试Java或者C这种巨麻烦的编译语言,print仍然是常用工具。当然,我们讲的是Python,是比Java和C要方便100倍的动态解释语言,因此这个print就更有力了。至于语法如何,不用我讲了吧。

2. reload
python本身就是一个交互式环境,你完全可以一边写代码,一边开一个python进程,然后用reload调用你写的模块,顺手传几个参数进去,看看运行的结果。

  1. # file name fac.py
  2. def factorial(n):
  3.         result = 1
  4.         for i in range(1, n+1):
  5.                 result *= i
  6.         return result
复制代码


  1. >>> fac.factorial(5)
  2. 120
复制代码


然后你用递归重写了factorial(注意,我这里把*替换成了+)

  1. # file name fac.py
  2. def factorial(n):
  3.         if n == 1:
  4.                 return result
  5.         else:
  6.                 return n + factorial(n-1)
复制代码


  1. >>> reload(fac)
  2. <module 'fac' from 'fac.py'>
  3. >>> fac.factorial(5)
  4. 15
复制代码


3. reload有一点限制,就是这个模块得能import得到。如果程序恰好不在PYTHONPATH里面,这一招就玩不转了。不过人不能让尿憋死对不对?所以python提供了exec和eval。

严格地说exec和eval并不是为了调试设计的,甚至我都不知道它们“应该”用在哪里。通常Perl程序员都喜欢,或者不得不用exec,eval实现一些很暴力,很变态的功能。不过由于Python的良好设计,这种滥用暴力的场合并不常见,因此Python初学者都对exec和eval不甚了解。这里正好借这个机会介绍一下者两个工具。

exec的语法是
exec(code, environment)

这个code可以是一个字符串,也可以是一个文件对象。下面我们用文件对象举例。

  1. >>> d = {}
  2. >>> exec(file('/tmp/fac.py', d)
  3. >>> d.get('factorial')(5)
  4. 15
复制代码


eval和exec的意思相近,不过其功能是计算而不是赋值。(接上面的例子)
  1. >>> eval('factorial(12)', d)
  2. 15
复制代码


这里environment是一个dictonary,因此当python执行完code之后,他会把所有的东西都放在这个environment里面。如果你不指定environment,python会在当前的environment里执行这段代码。如果你刚运行了一个factorial,接着又执行了这个fac.py,那么这段代码里的factorial就会取代你刚运行的factorial。因此,强烈建议你,总是指定一个environment


4. python -i
exec也好,reload也罢,对于调试单独一个类或者方法,是很方便的,但是如果在写要用到这些类或者方法的程序时,该怎么调试呢?写一个wrapper方法。好主意,实际上我自己就经常这么做。不过python的命令行参数提供了一个更棒的方法, -i

  1. # test.py
  2. def factorial(n):
  3.     if n == 1:
  4.         return 1
  5.     else:
  6.         return n * factorial(n-1)

  7. def sum(n):
  8.     if n == 1:
  9.         return 1
  10.     else:
  11.         return n + sum(n-1)

  12. result = 0
  13. for i in range(5, 7):
  14.     result += factorial(i) + sum(i)

  15.     if i == 6 :     # our debugging break point
  16.         break       #
复制代码


  1. python -i test.py
  2. >>>
  3. >>> dir()
  4. ['__builtins__', '__doc__', '__file__', '__name__', 'factorial', 'i', 'result', 'sum']
  5. >>> result
  6. 876
复制代码


5. logging
logging是一个远比print更强大的调试工具。Python的logging模块非常强大,任何一个严肃的Py开发人员都应该学会使用这个模块。建议大家从Python的文档入手,学习这个模块。这里我就不多讲了。

6. pdb, idle,komodo,windpdb,以及其他调试工具。
很遗憾,除了idle和komodo用过几次,其他的都是只闻其名,实在是不知道该怎么介绍。不过我倒是一点也不觉得遗憾。就我个人的感觉,有了上面5个工具,完全够用了。

[ 本帖最后由 shhgs 于 2008-9-2 12:20 编辑 ]

论坛徽章:
6
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:582015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-08-30 08:16 |显示全部楼层
习惯断点了,

论坛徽章:
0
发表于 2008-08-30 11:43 |显示全部楼层
多谢LZ的精彩讲解,解除了我许多疑惑,哈哈~
PS:标题拼错了……

[ 本帖最后由 jjj137 于 2008-8-30 12:14 编辑 ]

论坛徽章:
0
发表于 2008-09-01 09:06 |显示全部楼层
感谢楼主分享。呵呵
不错不错

论坛徽章:
0
发表于 2008-09-01 14:20 |显示全部楼层
学习一下,
我现在只会一个个的跟踪程序变量,就是在命令行输入变量的名字,看看哪个出现问题。

论坛徽章:
0
发表于 2008-09-01 17:46 |显示全部楼层
这个对比较有用!

论坛徽章:
0
发表于 2008-09-03 09:11 |显示全部楼层
很很大白菜的问一下,怎么实现单步跟踪调试,虽然大家不推荐这么干,但是有这个还是很方便查错的?

论坛徽章:
0
发表于 2008-09-03 09:20 |显示全部楼层
good.

论坛徽章:
0
发表于 2008-09-03 13:58 |显示全部楼层
原帖由 Vinge 于 2008-9-3 09:11 发表
很很大白菜的问一下,怎么实现单步跟踪调试,虽然大家不推荐这么干,但是有这个还是很方便查错的?

呵呵,单步调试就要借助工具了,见楼主的第六条。
另外貌似ulipad也带了一个调试工具,没用过不知怎么样。

论坛徽章:
6
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:582015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-09-03 19:27 |显示全部楼层
Assert 算吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP