python中的异常处理和调试

python中的异常处理和调试

今天我们就来扒一扒异常处理和调试的那些事……(蜗牛一手还拿着咬了半拉的煎饼)

首先要明白的一点是,程序发生异常之后,程序的流程会改变,程序的控制权将会转移到异常处理器。异常发生时,如果没有程序处理异常,那python会接受处理,python解释器将输出一些相关的信息并终止程序的运行。

python中常见的几种异常:
这里写图片描述

  • python中的异常采用继承结构创建。

try……except

这大概是每个语言都有的异常机制了。

将可能出现问题的代码块放到try中,如果出现了异常,则会自动生成一个异常对象,这个对象包括了异常的具体信息和错误位置等。

举个栗子:

try:
    file('hello.txt','r')
    print "读文件"
except IOError:
    print "file is not excist"

except:
    print "程序异常"

读一个不存在的文件,会产生异常,直接跳到第四行。

后边的那个except是不会执行了。因为上边捕获了IOError。

try……except……finally

是try……except的升级版,后边加一个finally语句,意思是无论异常是否发生,finally子句都会被执行。

  • 其实finally异常多用于关闭因为异常而不能的关闭的已经打开的资源。

举个栗子:

try:
    f=file('hello.txt','r')
    print "读文件"
except IOError:
    print "file is not excist"

finally:
    f.close()

执行上述代码有错。
为什么?
等下再说为什么有错,但是这个结构是对的,也很好的解释了“finally”语句用于关闭打开的资源。

再来看错误:

NameError: name ‘f’ is not defined

f定义在try的语句块中,是局部变量,在finally的语句块中f没有作用域。

正确的代码童鞋们可以试试(提示:try语句可以嵌套哦)

raise语句

发生错误时,python自动引发异常,但是也可以通过raise显示引发异常。但是一旦执行了raise语句,raise语句之后的代码不会执行。

自定义异常

自己可以定义异常,用于弥补python没有定义的异常

  • 自己定义的异常必须继承Exception类。

  • 自己定义的异常以Error结尾。因为不是python提供的异常,所以只能使用raise手动去引发(抛出)异常。

(以下内容来自廖雪峰的教程)

class FooError(StandardError):
    pass
def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n

if __name__=="__main__":
    foo(0)

首先定义了自己的异常类型FooError,他一定要继承一个异常的基类:StandardError,它是python提供的一个基类。

这里弄个断点,我们去看一下异常的继承关系。
python2.5 版本的异常定义在exception模块中,并继承了基类BaseException。注意所有的错误类型都继承自 BaseException 。

Excepetion是最常用的异常类,包括StandardError,StopIteration,GeneratorExit等异常类。

断点回来,继承了StandardError的FooError,啥类体都没有,pass

在后边的raise FooError(‘invalid value: %s’ % s)语句中,记得要手动raise一个自定义的异常。

结果:

 raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0

可以跟踪自己的异常

再来看个例子:(来自廖雪峰教程)

def foo(s):
    n = int(s)
    return 10 / n
def bar(s):
    try:
        return foo(s) * 2
    except StandardError, e:
        print 'Error!'
        raise
def main():
    bar('0')
main()

在 bar() 函数中,我们明明已经捕获了错误,但是,打印一个 Error! 后,又把错误通过 raise 语句抛出去了,这不
有病么?
其实这种错误处理方式不但没病,而且相当常见。捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函
数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。

  • raise 语句如果不带参数,就会把当前错误原样抛出。

assert语句

assert和if差不多是近亲,用法很像。

只是assert 不满足的时候会抛出assert异常。

>>> t=("hello",)
>>> assert len(t)>=1
>>> t=("hello")
>>> assert len(t)>=1
>>> assert len(t)==1

第一行不会有问题,因为括号里面有逗号,代表这是个元组,而元组里面就一个元素hello。
第三行但如果没这个逗号,python会认为后边是个string,所以第四行没错,而第五行不满足assert条件会抛出AssertError。

Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    assert len(t)==1
AssertionError

assert还可以带信息给AssertionError

举个栗子:

>>> month=12
>>> assert 1<=month<=11,"month errors"

结果:

Traceback (most recent call last):
  ……
AssertionError: month errors

ps:1<=month<=11这样的语句python是支持的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值