python 错误捕获机制分析
python语言是编程中使用率在Top 3之内的语言。python语言以灵活与简单著称,那么越是灵活的语言越需要判断出错的功力。
简单示例
以下是一个简单的错误程序,被除数不可为0,那么看看该代码的执行。
a = b = c = a / b print c

出错报告是:在文件error_three.py 的第5行 c = a / b报错,原因是整数除法或者取模运算的被除数为0
解释异常被捕获的流程:当程序运行到 c = a / b时,有异常产生,然后python解释器就捕获了该异常,并判断异常的类型,最后将该异常抛出,终止了程序的运行
python的异常捕获原则是这样的:程序某一行产生异常,解释器会一层层的上报,寻找异常的捕获代码。如果解释一直上报到main()函数中都没有捕获异常的语句,那么main()函数会捕获到异常,并抛出异常。
下面看一个复杂一点的函数异常处理:
#coding:utf- def get_num():
num = int(input("input you num:"))
return num def fun_two():
num = get_num()
div = -num
return div def fun_three():
two_num = fun_two()
three_num = / two_num
print three_num if __name__ == '__main__':
fun_three()
这里产生异常的点有两个:
1、被除数为0,在13行
2、输入类型错误在4行
首先我们看第一个异常:

输入10,div = 10 - 10 = 0,three_num = 10 / 0,然后报错。
具体分析报错信息,从上到下:
1、错误出现在文件error_two.py中的19行,出错函数:fun_three
2、在fun_three中的14行,代码:three_num = 10 / two_num中报错,原因是:被除数不能为0。
按照python解释器的工作原理:程序在14行出错,然后一层层上报到main函数,main函数从上到下找到出错点。下面看看第二个错误是不是也符合这个规律。

出错解释:
1、程序在19行出错,出错函数是:fun_three
2、fun_three内部在13行出错,出错代码是函数:two_num = fun_two()
3、fun_two内部在8行出错,出错代码是函数:num = get_num()
4、get_num函数在第4行出错,出错代码是:num = int(input("input you num:")) 。出错原因是:类型错误,int()函数不能转化非数字类型的函数
从以上的分析来看,我们按照一个规律肯定能找到程序出错的地方和原因。但是光找到出错的地方还不够,还要能够自动的处理这些错误。程序要达到的效果是坚决不出错误,万一出了错误也要能够自动的捕获错误,记录下来。本着个原则,我们看看在python中是如果主动捕获错误的。
以第一个简单的程序为例,报错如下:

错误的确是显示出来了,但是程序也停止了。这里有三点要求没有达到:
1、程序终止了,后面如果还有重要代码也无法执行了
2、程序是给大众使用的,程序员肯定能看懂错误原因,但是普通人就不好说了。错误提示没有
3、程序出错也没有错误日志记录,当然前提是需要的话
捕获异常
那么给这个简单的小程序加一个异常捕获的代码:
#coding:utf-8
a = 10 b = 0
try:
c = a / b
except:
print "程序出现了异常"
else:
print c
再次执行看看:

这样异常就被except捕获到了。并且捕获到之后打印出except中的提示信息。
python中标准的程序异常捕获语句是:
try
可能出错的语句
except:
捕获到的异常
一直提到异常,前面我们也见过了两个异常,分别是:TypeError和ZeroDivisionError,这两个异常说的是类型异常和被除数为0。聪明的读者你肯定想到python已经定了常见的,大量的异常类型。是的,具体来说python定义的异常有如下:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
+-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
常见的异常类型如下:
AttributeError:属性错误,特性引用和赋值失败时会引发属性错误
NameError:试图访问的变量名不存在
SyntaxError:语法错误,代码形式错误
Exception:所有异常的基类,因为所有python异常类都是基类Exception的其中一员,异常都是从基类Exception继承的,并且都在exceptions python 模块中定义。
IOError:python ioerror,一般常见于打开不存在文件时会引发IOError错误,也可以解理为输出输入错误
KeyError:使用了映射中不存在的关键字(键)时引发的关键字错误
IndexError:索引错误,使用的索引不存在,常索引超出序列范围
TypeError:类型错误,内建操作或是函数应于在了错误类型的对象时会引发类型错误
ZeroDivisonError:除数为0,在用除法操作时,第二个参数为0时引发了该错误
ValueError:值错误,传给对象的参数类型不正确,像是给int()函数传入了字符串数据类型的参数。
标准异常捕获
在上面的处理函数中我都是用异常的基类去捕获异常的。这样做有一个不好的地方就是我们虽然能捕获异常,但是不能看出是哪一个异常。使用更精确的异常捕获类型能够精确找到出错点。
#coding:utf-8 def get_num():
try:
5 num = int(input("input you num:"))
6 except TypeError,e:
7 print e def fun_two():
num = get_num()
div = 10 -num
return div def fun_three():
two_num = fun_two()
three_num = 10 / two_num
print three_num if __name__ == '__main__':
fun_three()

怎么还是报错了,不是捕获了异常了吗?这里要看清楚,我是在输入的时候捕获的异常,并且异常也捕获到了,看前两行的输出信息:int()函数的参数一定要是一个字符串或者数字,不能使type类型。按照之前的规律去分析一下这里的报错在哪里。
1、报错在21行,函数fun_three
2、fun_three函数中的15行报错,two_num = fun_two()
3、fun_two函数中11行报错,报错代码是:div = 10 - num,报错信息是:TypeError,不支持int类型和空类型的变量相减
这里就是另一个错误了,输入在前,相减在后。至少说明两个问题:一、在输入时精确捕获到异常TypeError;二、捕获异常后面的代码能够正常运行。那么我虽然捕获到了异常,但程序还是异常终止了。原因在于捕获的位置不是最佳位置。尝试换一个位置来试试。
#coding:utf-8 def get_num():
num = int(input("input you num:"))
return num def fun_two():
num = get_num()
div = 10 -num
return div def fun_three():
try:
two_num = fun_two()
three_num = 10 / two_num
print three_num
except (TypeError,ZeroDivisionError),e:
print e if __name__ == '__main__':
fun_three()
将错误捕获加在最后调用的地方,并且针对两种可能出现的错误都做了捕获。那么这里理论上就能捕获两个可能出现的错误。我们看看结果如何:


可以看到两种错误都能够捕获到,并且没有报出异常信息。以python解释器错误抛出的规则来分析:
一、当输入为字符串“str”时,程序报错,然后解释器一层层向上寻找异常捕获的语句;
二、在get_num()函数中没有,向上寻找调用它的函数fun_two(),任然没有;
三、继续向上寻找调用fun_two的函数fun_three,在fun_three中寻找到捕获异常的语句except (TypeError,ZeroDivisionError),e
四、捕获到异常之后抛出异常。
python标准出错处理
在编码中常用的出错处理机制是:
try:
可能出错的地方
except:
错误捕获,出错时要执行的代码
else:
没有错误时要执行代码
finally:
不管有没有错误都要执行的代码
这种出错处理适用于不管有没有出错,都一定要执行某些操作。常见的是打开了文件,不管是否打开成功,都要关闭。
例如:
#coding:utf- try:
f = open('file.txt','w')
print f.read()
f.close()
except IOError,e:
print e
else:
print f.read()
finally:
if f:
f.close()
以写方式打开一个文件,但是却有读操作,这样就会报错。虽然按照文件处理规范,在打开之后也添加了关闭文件的代码,报错之后的代码不会执行,所有这个错误会被except IOError捕获。但是捕获之后打开的文件并没有关闭,文件连接是消耗资源的事件,那么在finally中就要关闭文件连接。
合适的错误捕获能够增加程序的健壮性,是在编码中一定要能够熟练使用的技巧。
python 错误捕获机制分析的更多相关文章
- python错误处理—try…catch…finally、调用栈分析
		
高级语言包括python一般都内置了一套try…catch…finally的错误处理机制: >>> try: ... print('try...') ... r = 10 / 0 . ...
 - python错误处理之try...except...finally...错误处理机制。
		
今天学习了python的错误处理. 在程序处理的过程中,经常会出现错误,一旦出错就会非常麻烦.所以有的高级语言通常都内置了一套 try...exept...finaly...的错误处理机制,pyth ...
 - Map/Reduce 工作机制分析 --- 错误处理机制
		
前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...
 - 第十一篇:Map/Reduce 工作机制分析 - 错误处理机制
		
前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...
 - python 错误处理
		
在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因.在操作系统提供的调用中,返回错误码非常常见.比如打开文件的函数open(),成功时返回文件描 ...
 - python 错误、调试、单元测试、文档测试
		
错误分为程序的错误和由用户错误的输入引起的错误,此外还有因为各种各样意外的情况导致的错误,比如在磁盘满的时候写入.从网络爬取东西的时候,网络断了.这类错误称为异常 错误处理 参考链接:https:// ...
 - 如何捕获和分析 JavaScript Error
		
前端工程师都知道 JavaScript 有基本的异常处理能力.我们可以 throw new Error(),浏览器也会在我们调用 API 出错时抛出异常.但估计绝大多数前端工程师都没考虑过收集这些异常 ...
 - python的反射机制
		
转载自:http://www.cnblogs.com/feixuelove1009/p/5576206.html 对编程语言比较熟悉的朋友,应该知道"反射"这个机制.Python作 ...
 - Linux信号(signal) 机制分析
		
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
 
随机推荐
- 【PAT】B1015 德才论
			
这道题算是挺简单,我在群里看到的别人琢磨好久过不去,大多是因为没有考虑好四种等级的判断条件 一定要保证四种判断条件正确. 下面这是我的代码,比较笨.后边有别人那学来的聪明些的方法 #include&l ...
 - SQLServer删除数据
			
使用SSMS删除数据 1.连接数据库.选择数据表->右键点击,选择所有行(或者选择前200行). 2.在数据窗口中选择数据行(注意点击最左边列选择整个数据行)->在最左侧右键点击-> ...
 - Github: 从github上拉取别人的源码,并推送到自己的github仓库
			
比如说,将 https://github.com/lizhenliang/tomcat-java-demo 迁移到 https://github.com/lousia001/tomcat-java-d ...
 - Docker: Harbor一些小知识
			
镜像文件上传到私有仓库harbor后,镜像的物理存储位置在哪里? 这些信息记录在docker-compose.yml里,通过观察发现 镜像存储在了宿主机的 volumes: - /data/regis ...
 - Linux Collection:软件配置
			
PAS Debian 9安装最新版Firefox( Firefox 58+/Quantum) Debian 9(Strech)的仓库包含的是firefox-esr(52)版本:需要安装最新版,有如下两 ...
 - C++中 #if 和 #ifdef 区别
			
以#开头的都是预编译指令,就是在正式编译之前,编译器做一些预处理的工作#if 条件语句程序段1 //如果条件语句成立,那么就编译程序段1#endif程序段2//如果条件不语句成立,那么就编译程序段2# ...
 - 【Python 23】52周存钱挑战3.0(循环计数for与range)
			
1.案例描述 按照52周存钱法,存钱人必须在一年52周内,每周递存10元.例如,第一周存10元,第二周存20元,第三周存30元,直到第52周存520元. 记录52周后能存多少钱?即10+20+30+. ...
 - 新建swap分区的规划、挂载和自动挂载示例
			
注:来自Linux系统管理_磁盘分区和格式化的扩展 Linux系统管理_磁盘分区和格式化:http://murongqingqqq.blog.51cto.com/2902694/1361918 思路: ...
 - HTML DOM 事件对象  ondragend 事件
			
学习网站:http://www.runoob.com/jsref/event-ondragend.html 定义和用法 ondragend 事件在用户完成元素或首选文本的拖动时触发. 拖放是 HTML ...
 - JavaScript验证输入的字符是否包含表情
			
以下是验证代码: function isEmojiCharacter(substring) { for ( var i = 0; i < substring.length; i++) { var ...