• 《pyhton学习手册》 第33章 异常编码细节


    try/except/else语句

    这些语句的一般的格式如下图所示

    其中try中定义了主要执行的动作。except中定义了try语句当中发生异常的处理器。else定义了没有发生异常时候的处理器。

    try语句运行的方式:try语句启动的时候,pyton会标识当前的程序环境,如果有异常发生,才返回这里。try首行下面的语句先被执行,然后根据执行的程序的情况,发生下面不同的动作:

    -try里面的代码块的确发生异常,python就会跳回try,执行第一个符合引发异常的except字句下面的语句。当except执行后,控制权会到整个try语句后(try/except/else所有语句)继续执行。

    -try里面的代码块发生异常,但是没有符合的except字据,那么异常会向上传递。

    -try里面的代码没有异常,python会执行else行下的语句,控制权会在整个try语句下继续。

    try语句分句

    -在python2.5开始,finally可以和except和else出现在同一个语句当中,在2.5以前,finally只能单独的和try结合使用。

    -excpet: 这种形式可以捕获任何形式的异常,是一种通用的功能。except Exception:  捕获一个名为Exception的异常,效果几乎和空的except具有相同的效果,但是忽略和系统退出相关的异常。

    -一旦捕获了异常,控制权会在捕捉的地方继续向下(也就是在try之后),没有直接的方式可以回到异常发生的地方那个,可以运行下面的代码:

    try:
        print('A')
        raise IndexError
        print('B')
    except IndexError:
        print('C')
    print('D')

    输出结果如下:

    A
    C
    D

    可以发现,在捕获到IndexError异常以后,try语句里面的内容不会向下执行(即不会输出‘B’),而是在整个try语句后继续运行。

    try/finally语句

    -当try代码块当中有异常的时候,python会回来运行finally里面的代码块,但是紧接着会把异常向上传递,传到较高等级的try或者顶层默认处理器,程序不会在try语句下继续执行。和except不同的是,finally不会终止异常,而是在finally代码块执行后,一直处于发生状态

    -try/finally最典型的另个应用场景是在关闭一个文件的时候, 或者关闭一个服务器连接的时候。

    统一try/except/finally语句

    在python2.5以前,try语句有两种形式,而且是独立的两种语句,finally无法和except和else混合,但是在2.5后的版本,这两个语句可以进行合并了,他们的形式如下:

    合并try的例子

    这里将通过一个聚合的例子来看一下前面说过的东西,代码如下:

    sep = '-'* 32 +'
    '
    print(sep + 'Exception raised and caught')
    try:
        x = 'spam'[20]
    except IndexError:
        print('except run')
    finally:
        print('finally run')
    print('after run')
    
    print(sep + 'No Exception rasied')
    try:
        x = 'spam'[2]
    except IndexError:
        print('except run')
    finally:
        print('finally run')
    print('after run')
    
    print(sep+'No Exception raised with else')
    try:
        x = 'spam'[2]
    except IndexError:
        print('except run')
    else:
        print('else run')
    finally:
        print('finally run')
    print('after run')
    
    print(sep + 'Exception rasied but not caught')
    try:
        x = 1 / 0
    except IndexError:
        print('except run')
    finally:
        print('finally run')
    print('after run')

    运行结果如下:

    --------------------------------
    Exception raised and caught
    except run
    finally run
    after run
    --------------------------------
    No Exception rasied
    finally run
    after run
    --------------------------------
    No Exception raised with else
    else run
    finally run
    after run
    --------------------------------
    Exception rasied but not caught
    finally run
    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc2	est1.py", line 38, in <module>
        x = 1 / 0
    ZeroDivisionError: division by zero

     raise语句

    raise语句通常有三种形式

    raise <instance>  #raise 一个类的实例
    raise <class>     #生成并且raise一个类的实例
    raise             #raise最近生成的异常

    raise总是引发一个类的实例,所以第一种方法是最常用的,在使用第二种方法的时候,调用了类的无参构造方法来生成类的一个实例,不加任何参数的raise产生最近生成的一个异常。

    except name as X: 子句的作用:变量X将会分配给引发中所提供的实例,我们看下面的一个例子:

    class MyExcp(Exception):
        pass
    try:
        raise MyExcp('nihao')
    except MyExcp as X:
        print(X.args)

    上面的例子当中,定义了我们自己的异常,在raise的时候,传入了参数'nihao',然后在捕获的时候捕获这个对象,输出这个对象的参数,最后的结果是: 

    ('nihao',) 

    空的raise语句作用,它重新引发当前异常,运行如下代码:

    try:
        1/0
    except Exception as E:
        print('nihao')
        raise

    得到结果:

    nihao
    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc2b.py", line 2, in <module>
        1/0
    ZeroDivisionError: division by zero

    这个时候异常会继续上抛,如果没有raise,那么程序将在try后继续执行。

    assert语句

    assert可以看做是带有条件的raise语句,assert的一般语法是 assert <test>,<data>  当test的部分为错误(False)的时候,触发异常。

    assert的一个作用是用来收集用户自定义的约束条件,因为python会自动帮我们收集程序当中出现的错误。

    比如,当x ≥0的时候,触发一个错误,x ≥0 是我们自己定义的约束,运行如下代码:

    def fun(x):
        assert x < 0,'x must be negative'
        return x ** 2
    fun(3)

    输出结果如下:

    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc2b.py", line 4, in <module>
        fun(3)
      File "D:applicationeclipseworkspaceyichangc2b.py", line 2, in fun
        assert x < 0,'x must be negative'
    AssertionError: x must be negative

    所以assert可以在我们检查我们程序定义的约束的时候起到很大的作用。

    with/as环境管理器

    with语句的基本格式如下:

    with expection [as variable]:
        with-block

    如果有as variable的话,那么会接收内部__enter__返回出来参数。要实现环境管理器,使用with 方法,那么对象里面必须有__enter__和__exit__方法的。

    我们来编写一个这样的类:

    class TraceBlock:
        def message(self):
            print('message excute')
        def __enter__(self):
            print('enter excuete')
            return self
        def __exit__(self,type,value,tb):
            if type is None:
                print('exit normally
    ')
            else:
                print('raise a excpetion')
            #print('type:',type,'
    value:',value,'
    tb:',tb)
    with TraceBlock() as t:
        t.message()
        print('not error')
    with TraceBlock() as t:
        t.message()
        raise TypeError
        print('error')

    运行结果如下:

    enter excuete
    message excute
    not error
    exit normally
    
    enter excuete
    message excute
    raise a excpetion
    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc2b.py", line 18, in <module>
        raise TypeError
    TypeError

     其实我们关系的是发生异常的时候,程序是怎么运行的,我们修改上面的代码

    class TraceBlock:
        def __enter__(self):
            return self
        def __exit__(self,type,value,tb):
            print('type:',type,'
    value:',value,'
    tb:',tb)
    with TraceBlock() :
        1/0

    输出的结果如下:

    type: <class 'ZeroDivisionError'> 
    value: division by zero 
    tb: <traceback object at 0x022ADE18>
    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc2b.py", line 8, in <module>
        1/0
    ZeroDivisionError: division by zero

     说明,发生异常的时候,异常的参数会传入__exit__里面,在里面进行处理。


     总结:

       这一章讲了一些 try语句的细节,还有raise语句,assert语句以及with语句的细节。

  • 相关阅读:
    滑动窗口模板
    交换机命令
    针对织梦程序列表字段内可有可无的显示方法
    dedecms中常见问题修改方法
    redis系列之------字典
    1.InfluxDB-官方测试数据导入
    MYSQL第二课
    centos6.8下hadoop3.1.1完全分布式安装指南
    Mysql—添加用户并授权
    什么是全文检索
  • 原文地址:https://www.cnblogs.com/jiaxin359/p/7302223.html
Copyright © 2020-2023  润新知