异常处理的作用
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!(这里的大黄页通常是写代码是用户访问网页,如果出现错误之后返回的一个黄色的报错页面通常称为:大黄页)
例子:
拿咱们刚开始学的时候遇到的问题来举例:
未做异常处理的:
#!/usr/bin/env python#-*- coding:utf-8 -*-str_input = 'abc'number = int(str_input)print number报错信息:'''Traceback (most recent call last): File "C:/Github/homework/tianshuai/boke.py", line 5, innumber = int(str_input)ValueError: invalid literal for int() with base 10: 'abc'
做了异常处理的:
try: str_input = 'abc' number = int(str_input) print numberexcept Exception,e: print "\033[32;1m出现错误如下\033[0m" print e#输出结果:'''出现错误如下invalid literal for int() with base 10: 'abc'
1.异常处理基础
拿下面的代码来说:
假如我有一个程序,获取用户输入的数字!这里我不能控制用户输入什么。
看下面输入了一个字符串,这里我可不可以用异常处理来告诉用户,你的输入字符串啊!
user_input = raw_input("\033[32;1m请输入数字:\033[0m")number = int(user_input)#请输入数字:sdlkf'''Traceback (most recent call last): File "E:/ѧϰ/GitHub/homework/tianshuai/master.py", line 5, innumber = int(user_input)ValueError: invalid literal for int() with base 10: 'sdlkf'
异常处理情况:
try: #正常逻辑代码 user_input = raw_input("\033[32;1m请输入数字:\033[0m") number = int(user_input)except Exception,e: #这个e是对象Exception类创建的!Exception这里面封装了你上面逻辑块出现问题的所有错误 #逻辑代码出现错误,这里的代码块就是如果上面的代码出现问题之后执行这个代码块的内容 print e #如果这个e你不想要,可以自己定义 #这里也可以记录日志,把错误的详细记录,错误详细在e里了!#结果:'''请输入数字:sdfsinvalid literal for int() with base 10: 'sdfs'
2. 异常处理种类
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性xIOError 输入/输出异常;基本上是无法打开文件ImportError 无法引入模块或包;基本上是路径问题或名称错误IndentationError 语法错误(的子类) ;代码没有正确对齐IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]KeyError 试图访问字典里不存在的键KeyboardInterrupt Ctrl+C被按下NameError 使用一个还未被赋予对象的变量SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)TypeError 传入对象类型与要求的不符合UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它ValueError 传入一个调用者不期望的值,即使值的类型是正确的
ArithmeticErrorAssertionErrorAttributeErrorBaseExceptionBufferErrorBytesWarningDeprecationWarningEnvironmentErrorEOFErrorExceptionFloatingPointErrorFutureWarningGeneratorExitImportErrorImportWarningIndentationErrorIndexErrorIOErrorKeyboardInterruptKeyErrorLookupErrorMemoryErrorNameErrorNotImplementedErrorOSErrorOverflowErrorPendingDeprecationWarningReferenceErrorRuntimeErrorRuntimeWarningStandardErrorStopIterationSyntaxErrorSyntaxWarningSystemErrorSystemExitTabErrorTypeErrorUnboundLocalErrorUnicodeDecodeErrorUnicodeEncodeErrorUnicodeErrorUnicodeTranslateErrorUnicodeWarningUserWarningValueErrorWarningZeroDivisionError
#!/usr/bin/env python#-*- coding:utf-8 -*-__author__ = 'wyf'#实例1:list = [1,2,3]try: list[10]except IndexError,e: print e#结果:list index out of range#实例2:dic = { 'k1':123,'k2':456}try: dic['k3']except KeyError,e: print e#输出结果为:'k3'#例子3s1 = 'hello'try: int(s1)except ValueError,e: print e#输出结果:invalid literal for int() with base 10: 'hello'
小实例中介绍的都是我们之前经常遇到的问题,因此你已经知道是什么类型的错误了,因为你可以在except的时候指定错误类型。
但是这次我不知道了结果是什么样子的?
s1 = 'hello'try: int(s1)except IndexError,e: print e
输出结果:直接报程序出错了:
写程序的时候需要考虑所有可能出现的异常,可以这么写:这个是从上往下依次匹配的,上一个没有就会找下一个,最后一个是万能的能接受各种错误:
1 s1 = 'hello' 2 try: 3 int(s1) 4 except IndexError,e: 5 print e 6 except KeyError,e: 7 print e 8 except ValueError,e: 9 print e10 except Exception,e: #用这个万能的异常去捕获异常11 print e
在这个地方有个疑问,既然有万能的,为啥还有分出类型的错误呢?不是没事找事么?那我问你一个问题,你要对某种类型的错误做相关处理,你用这个万能的就不行了吧?
1 s1 = 'hello'2 try:3 int(s1)4 except KeyError,e:5 print '键错误'6 except IndexError,e:7 print '索引错误'8 except Exception, e:9 print '错误'
3.异常的其他结构
else 没有失败要执行的代码端 finally 是无论成功失败都执行==== try else finnaly
#!/usr/bin/env python#-*- coding:utf-8 -*-try: #这一块才是最主要的逻辑处理块,所有的逻辑处理都是放在这里的 passexcept KeyError,e:#如果出现KeyError错误,首先被他捕获,下面的except就不执行了 passexcept Exception,e:#如果上面的错误没有找到就去,万能异常里找 passelse:#这里什么时候执行呢,逻辑代码里为出现异常这个代码快才执行 passfinally: #不管上面是否出现异常,最后执行完之后,这里永远执行!finally什么时候用?你上面执行一个操作,连接数据库,我这里就可以执行,断开数据库释放资源!(举例) pass'''上面的代码就是全部的异常处理的内容'''
4.主动出发异常
有时候我们需要主动出发一个异常来帮我们定位问题:
#!/usr/bin/env python#-*- coding:utf-8 -*-__author__ = 'wyf'a = Falsetry: if a: print 'aaaa' else: raise Exception('出错误了,处理一下吧')#这样我们自己触发了一个错误,而不是抛到了万能的异常接收中except Exception,e: print e
5.自定义字符串
咱们看下异常处理的代码!咱们这里知道e是一个对象,这个e是由Exception类创建的,咱们print这个e是一个字符串,那么这个字符串是怎么来的呢?
#!/usr/bin/env python#-*- coding:utf-8 -*-try: int('sdfsdfs')except Exception,e: print e#执行结果:'''invalid literal for int() with base 10: 'sdfsdfs''''
在看这个代码:没定义__str__方法的,它输出的是一个object的内存地址
class A(object): passobj = A()print obj#执行结果:'''<__main__.A object at 0x0000000000AA2A20>'''
__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
1 class Foo(object): 2 3 def __str__(self): 4 return 'zhe ge shi yi ge ce shi' 5 6 obj =Foo() 7 print obj 8 9 #执行结果:10 #zhe ge shi yi ge ce shi
现在我们可以自定义一个异常模块:
1 class zidingyierror(Exception):#自己定义一个异常并继承Exception,除了自己定义的异常Exception的万能异常也可以使用 2 def __init__(self,msg=None): 3 self.msg = msg 4 5 def __str__(self): 6 if self.msg: 7 return self.msg #定义了错误了信息提示的错误 8 else: 9 return 'something error' #如果不传输消息则输出默认信息10 11 try:12 #raise zidingyierror('zhe shi yi ge ce shi')13 raise zidingyierror()14 except Exception,e:15 print e
6.断言
assert 1 == 1 #如果条件满足就不报错,如果条件不满足就会报错assert 1 == 2 '''这个和 raise Exception('string') 只要你定义了raise肯定会报错这个一般什么时候使用,比如我写了一个软件,上面有些条款:你必须接受,你不接受我就不让你用!