社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python代码调试的那些“最少且必要”技巧

脚本之家 • 5 年前 • 723 次点击  

脚本之家

你与百万开发者在一起


异常处理模块能帮助我们在运行期间处理异常信息,但Python代码还有更为基础的错误——语法错误和逻辑错误

语法错误相对简单,在解释器的帮助下,我们很快就能定位错误所在。但对逻辑错误的调试就难多了,这些语法或逻辑层面的错误,构成了各式各样的代码bug。

为了调试错误,我们需要知道,出错时哪些变量的值是正确的,哪些变量的值是错误的。因此,我们需要掌握一些代码调试的基本技巧。


本文选自《Python极简讲义:一本书入门数据分析与机器学习》一书。这是一本图文并茂、简单易读的Python极简讲义,以掌握“最少必要知识”为写作理念,对初学者十分友好!


01 利用print()输出观察变量

第一种方法,简单而有效,直接而粗暴,就是用print()把需要观察的变量打印出来,如下所示。

【例1】 print()输出观察变量(print-err.py)

01   def foo(s):
02        n = int(s)                     #字符串转换为整型
03       print('n = {}'.format(n))   #输出观察变量n的值
04       return 10 / n
05   
06   foo('0')


运行结果

n = 0
---------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
……
input
-9-d21f20e5d17e> in foo(s)
      2     n = int(s)
      3     print('n = {}'.format(n))
----> 4     return 10 / n
      5 
      6 def main():
ZeroDivisionError: division by zero


根据打印处的信息(第3行)和错误信息(division by zero),我们可以很容易地定位错误所在:代码第4行,作为分母,n值为0。

02  assert断言

用print()观察变量的不足之处在于,调试完毕后,我们还得手动将它们删掉,如果调试工作量较大,造成print()满天飞,删除大量print()语句的工作量也不容小觑。而且,如果程序中到处充斥着print()语句,输出信息也会非常繁杂,给程序员造成困扰。

因此,就有了第二种方法—断言(assert)。凡是可用print()来辅助查看的,都可以用assert来替代。它用来测试某个条件(condition)的布尔值,系统默认这个条件为真,此时断言悄然无息,我们感知不到它的存在。但是,一旦条件为假,就会触发异常。assert的语法格式如下。

assert    #第一种情况,不给出错误信息


在Python中,可以把assert理解为简化版的异常处理,它与如下语句等价。




    

if not     
   raise AssertionError


assert后面也可以紧跟参数,给出更为详细的错误信息,示例如下。

assert  [, arguments]     #第二种情况,给出错误信息(可选项)


这种情况等价于如下语句。

if not condition:
    raise AssertionError(arguments)


下面我们通过具体示例来说明assert的用法,见【例2】。

【例2】assert的用法(assert_no_err_msg.py)

01   def avg(score):
02       assert len(score) != 0
03       return sum(score) / len(score)
04   
05   score = []
06   print("平均分数为:",avg(score))


运行结果

AssertionError                            Traceback (most recent call last)
input
-11-56d552b0cddd> in <module >
      4 
      5 score = []
----> 6 print("平均分数为:",avg(score))
input-11-56d552b0cddd> in avg(score)
      1 def avg(score):
----> 2     assert len(score) != 0
      3     return sum(score)/len(score)
      4 
      5 score = []
AssertionError:


代码分析

由于代码的第05行是一个空列表,其长度为0,因此会让第02行的判断条件len(score) != 0 为假,这时就会触发异常,导致程序终止运行。此时,如果将第05行代码修改如下:

05   score = [90,85,78]


整个程序将能正常运行,运行结果如下。

平均分数为: 84.33333333333333


使用assert的好处在于,当判断条件为真时,用户是感觉不到assert的,因为assert只有当判断条件为假时才“刷存在感”,给出错误信息。错误信息一旦给出,在某种程度上就定位了代码的bug所在,从而达到了程序调试的目的。调试完毕后,用户无须删除assert语句。

【例2】中的assert并没有给出错误信息,可读性不强。事实上,我们还可以显式给出错误信息。我们可以如下修改【例2】的第02行代码。

assert len(marks) !0"列表为空,咋整啊!"


这里,断言条件后面的"列表为空,咋整啊!",就是条件一旦为假时输出的错误信息。我们假设,此时第05行依然为空列表,这时【例2】的运行结果如下。




    

AssertionError                            Traceback (most recent call last)
input
-13-a477886d663d> in <module>
      5 score = []
      6 # score = [90,85,78]
----> 7 print("平均分数为:",avg(score))
input-13-a477886d663d> in avg(score)
      1 def avg(score):
----> 2     assert len(score) != 0,  "列表为空,咋整啊!"
      3     return sum(score) / len(score)
      4 
      5 score = []
AssertionError: 列表为空,咋整啊!

很明显,有了错误信息,就更容易找到代码的错误所在了。

如果断言太多,也会遭遇与print()类似的处境,异常信息会让我们“应接不暇”。如果不需要断言来帮忙,则在命令行启动Python解释器时可用“-O”参数来关闭assert,如下。

python -O assert_no_err_msg.py    #选项是大写的字母O,而非数字0




除了前面提到的利用print()assert进行调试,我们还可以使用IDE(如PyCharm等)进行调试,这些集成开发环境有着非常好用的“单步调试功能”,同时配合控制台的输出,也能比较便捷地定位错误。

当我们开发的项目规模比较大时,我们会发现,logging才是终极武器。logging是Python的日志模块。使用这个模块的好处在于,它允许我们指定记录信息的级别,有debug、info、warning、error等。

我们可以根据需要输出不同级别的信息。例如,当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debug和info就不起作用了。这样一来,我们就不必担心太多输出信息会冲淡关注力。

关于这个模块的知识,就留给“爱折腾”读者自学吧。高手,永远都是自学出来的!

相关图书

《Python极简讲义:一本书入门数据分析与机器学习》是一本理论结合实战,娓娓道来的入门好书。书中提供了入门数据科学领域的 极简必要知识 

不同于其他图书,本书不求全,但求精。这里的“精”是指,给出入门数据分析的“极简必要知识"( Minimal Actionable Knowledge and Experience,MAKE )。在极短的时间内,掌握数据分析的MAKE之道,这是本书的一大特色。

本书脉络


大咖推荐

  • 董付国,知名Python讲者、16本Python系列图书作者
  • 魏梦舒,微信公众号“程序员小灰”作者、《漫画算法》作者
  • 高扬博士,《白话强化学习与PyTorch》作者、金山办公AI技术专家
  • JulyCSDN千万级流量博主、七月在线CEO
  • 雷明,SIGAI创始人、《机器学习:原理、算法与应用》作者、百度前高级软件工程师



小编为我们喜爱阅读的书迷们免费送书。




留言点赞送书活动规则


留言点赞:留言分享您在学习或者使用python开发过程中的学习经验,或者其他一些学习经历。


>>> 活动参与
玩法1:机会总是靠自己去争取来的!小编将对留言进行精选,被精选的评论将会显示在页面中(由于微信功能限制,最多只能显示100条)。活动截止时获得点赞数最多的前2名朋友获得《Python极简讲义:一本书入门数据分析与机器学习》纸质书1本。
玩法2:踩楼送书活动,活动结束时踩中已放在百度云文件中指定楼层的精选留言将获得《Python极简讲义:一本书入门数据分析与机器学习》一本,共3名中奖者,动结束 后我们会在本公众号公布中奖楼层的解压密码


获奖楼层下载地址(文件解压密码会在2020年5月12日推送的中奖文章中公布)

百度云链接: 

https://pan.baidu.com/s/1i_WGN3QG02iKRWFJ7-RwKw 

提取码: kx5h

特别申明:

1、一位用户1个月内只能有1次获奖机会,让更多粉丝受益活动才更有意义

2、每一位用户只有1次留言机会,不允许重复留言~

请大家记住这三个1


活动截止时间:2020 年 05 月 12日 16:00 整。


精选书单 点蓝字即可 


 程序员的人生必做100件事中,一定有读这14本经典!

 程序员该怎么规划自己的成长路径?

 去年最畅销的IT类新书《漫画算法》出Python版了!

  如何用Python画一只机器猫?

 “Flutter中文网”社区创始人倾力撰写的网红书《Flutter实战》正式出版

 重磅 |《携程架构实践》《携程人工智能实践》上市啦!

 Python对我下手了!如何克服从入门到放弃?

更多好书请关注脚本之家官方书店

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/62794
 
723 次点击