Python 排错/排雷 指南(上)

2017-09-29 22:04:39 WenR0 猎户安全实验室

      Python 是一门简单而优雅的语言,想要快速实现想法的不错之选。对于初级Pyer,比较头疼的就是自己写的Py代码出现了一些错误。本文简单介绍Python 的排错方法,工具以及思路,帮助大家更加方便的解决遇到的问题。在此抛砖引玉,如有错误与遗漏,请不吝指教。



Lv1:观察与分析


“Oh, Watson. You see but you do not observe”


很多Pyer 在开始编码的时候,会有很多恐惧,很怕自己在哪里写错了,然后遇到一些未知的问题。在执行的时候,会弹出一个错误的提示。


首先,让我们来认识一下错误和异常。


在程序运行过程中,可能会出现各种的错误,有的错误是用户输入类型不同导致的,有的错误是异常的操作导致的(除0),还有的错误是无法在程序运行过程中预见的,比如网络问题,磁盘已满无法写入,权限问题无法写入。这一种错误叫做异常。


1. 异常是一个事件,该事件会在程序执行的过程中发生,影响了程序的正常执行

2. 一般情况下,在Python 无法正常处理程序时,就会发生一个异常。

3. 异常是Python 对象,表示一个错误。

4. 当Python脚本发生异常时,我们需要捕获处理它,否则程序会终止执行。


常见错误类型如下:


AssertionError

assert(断言)语句失败

AttributeError

试图访问一个对象没有的属性,比如foo.x ,但是foo没有x这个属性。

IOError

输入/输出异常,基本上是无法打开文件。

ImportError

无法引入模块或者包,基本上是路径问题

IndentationError

语法错误,代码没有正确对齐

IndexError

下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]

KeyError

试图访问字典里不存在的键

KerboardInterrupt

Ctrl + C 被按下

NameError

使用一个还未被赋值予对象的变量

SyntaxError

Python代码非法,代码不能解释

TypeError

传入对象类型与要求的不符

UnboundLocalError

试图访问一个还未被设置的局部变量,基本上是由于另一个同名的全局变量,导致你以为正在访问它

ValueError

传入一个调用者不期望的值,即使值的类型是正确的



例子:

变量覆盖:

由于Python 为动态语言,在赋值的过程中,不进行类型判断,如果没有很好的命名规范,会出现以下的情况

a = ‘abc’

a = 123

print a


除零:

10/0


== 还是 =

== 是判断

= 是赋值


If a=0:

   Print ‘yes’



Class 变量调用

第一张图片会提示name变量未定义

第二张是正确调用class A 内 name变量的正确姿势。


文件句柄:

在没有正确关闭文件句柄的情况下,调用文件句柄,会出现文件句柄错误。




省心的方法是使用with语句:


Lv2:实操与工具



想要正确的处理异常,需要使用到Python 自带的异常处理语句,


try..catch..finally..


try:

<语句>        #运行代码

except <名字>:

<语句>        #如果在try部份引发了'name'异常

except <名字>,<数据>:

<语句>        #如果引发了'name'异常,获得附加的数据

else:

<语句>        #如果没有异常发生

Finally:

<语句>        #无论什么情况,都会执行到这个语句




在了解了基本的异常处理语句后,开始介绍第一种最粗暴简单的调试方法:


print 大法好


在需要调试的地方,直接插入print 语句进行输出,人工进行判断。这个方法的好处在于快速直观,想看哪里点哪里。但是这种方法的不足很很明显,包含复杂输出的程序,很难找到到底print到哪里去了。


ipdb 下的精耕细作


有了print 不能解决所有问题,而且上下文环境复杂的时候,很难定位错误的位置。

这时候要祭出命令行Python debug 神器 ipdb

安装方法:

Pip install ipdb


如果国内网络情况堪忧,可以使用豆瓣的Pypi源

Pip install ipdb -i http://pypi.douban.com/simple/  --trusted-host pypi.douban.com


使用方法:

在需要调试的上下文环境下,插入:


在程序的运行过程中,会自动在这条语句的地方断点,并进入交互模式。


交互模式中,有很多的命令来帮助我们调试程序,常见的命令有:

L list 列出当前断点上下10行的代码

B break 下断点

S step 单步执行(进入函数)

N next 向下执行(不进入函数)

<enter> 重复上次命令

P print 和 python print 相同

Exit 退出


支持的全部命令通过 ? 来获取。

Tips: 通过step 调试,可以进入到函数内部实现,通过next 调试,如果遇到函数,则直接向下执行,得到结果。



Lv3:万能的搜索




我们不生产代码,我们只是代码的搬运工

我们遇到的问题,大部分情况下,别人都已经遇到过了,只要善用搜索引擎,从搜索引擎中得到答案。善用搜索引擎,节省生命。