• 【Python】你真的了解异常吗?-别再说你不了解异常啦


    主要内容:

    理解异常的基本概念
    掌握Python中异常的基本使用方法


    认识异常

    在我们前面经常提到 “程序运行出错” 这样的概念. 实际上, 这是Python解释器抛出了一个 异常

    异常的基本概念

    我们故意将 print 敲错, 解释器抛出了一个 NameError 异常

    a = 10
    prin(a)  # NameError: name 'prin' is not defined
    
    • 1
    • 2

    我们故意访问一个下标越界的列表, 解释器抛出了一个 IndexError 异常

    a = [1,2,3]
    print(a[100])	#IndexError: list index out of range
    
    • 1
    • 2

    我们故意打开一个不存在的文件, 解释器抛出一个FileNotFoundError 异常

    a = open('Z:/zzz.txt','r')
    #FileNotFoundError: [Errno 2] No such file or directory: 'Z:/zzz.txt'
    
    • 1
    • 2

    总结:

    • 异常是指程序执行过程中, 发生了错误. 根据不同的错误类型, 抛出不同类型的异常.
    • 如果一个程序抛出了异常, 如果不对这个异常做任何处理, 默认行为就是导致程序运行终止.

    这里我们要把Python的异常和C++/Java的异常做一个区分:

    因为Python是解释执行的, 所以语法错误和执行逻辑出现问题导致的错误都被Python统一成了异常.

    而C++和Java会预先对代码进行编译. 如果语法出错, 在编译期就能检查出来. 因此C++和Java的异常只涵盖运行时的错误.

    类比 Linux 的信号机制


    异常机制的意义

    异常机制归根结底是想办法帮我们简化代码的错误处理逻辑.

    C语言如何处理”异常“

    调用一个函数, 有可能会调用失败. C语言中通常使用函数返回一个错误的值的方式来判定函数的成功失败.-> 因此每个函数调用完成, 往往需要检查一下函数都返回值.

    每调用一个函数, 都要围绕这个函数写一大堆处理错误情况的逻辑, 导致处理正常逻辑的代码, 和处理异常
    逻辑的代码混淆在一起.

    通过异常处理机制, 就可以做到将正常逻辑和异常逻辑分离. 使代码的可读性更好.


    处理异常

    try捕捉异常

    我们使用 try 语句来捕捉异常(可能触发异常的代码放到try中). 使用except来具体处理异常

    如果异常能够被except捕捉到, 则不会影响程序继续执行.

    except可以指定一个具体的处理哪种类型异常. 如果try中抛出的异常类型, 不在except中, 那么仍然会程序终止.

    如:

    IndexError, e相当于捕捉到的这个异常对象的名字为e. 这个异常对象中包含了异常的具体信息.这个e相当于这个异常类的实例

    a = [1,2,3]
    try:
        print(a[100])
        print('hello')
    except IndexError as e:	
        print(type(e))
        print(e)
    #执行结果:
    <class 'IndexError'>
    list index out of range
    
    #如果把hello放上面:
    a = [1,2,3]
    try:
        print('hello')
        print(a[100])
    except IndexError as e:
        print(type(e))
        print(e)
    #执行结果:
    hello
    <class 'IndexError'>
    list index out of range
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    第一个是因为越界产生了异常,所以跳过后序代码,所以不打印hello 直接跳到except部分。

    注意:只要有抛出异常,异常之后的代码都不执行,直接终止当前代码块,直接到except


    try和except配合

    一个try语句, 可以和多个except语句联合工作.

    a = [1,2,3]
    try:
        print(a[100])
    except IOError as e:
        print(e)
    except IndexError as e:
        print(e)
    #执行结果
    list index out of range
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    try和else配合

    一个try语句, 还可以搭配else工作 (else不仅可以和while,for搭配,还可以和try搭配)

    a = [1,2,3]
    try:
        print(a[0])
    except IOError as e:
        print(e)
    except IndexError as e:
        print(e)
    else:
        print("程序没有异常")
    #执行结果
    1
    程序没有异常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    except可以不带具体的异常类型, 这样只要try中触发了任意的异常, except都能捕捉到

    a = [1,2,3]
    try:
        print('hello')
        print(a[100])
    
    except :
        print("捕获到异常")
    #执行结果:
    hello 
    捕获到异常
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    异常的基类:Exception类

    Python中内置的异常类, 其实都继承自 Exception 类. 所以上面的代码还可以写成

    a = [1,2,3]
    try:
        print(a[110])
    except Exception as e:
        print(e)
    else:
        print("程序没有异常")
    #执行结果:
    list index out of range
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    finally

    如果想执行一些不管是否触发异常, 都要执行到的代码, 可以放到finally语句块中.finally就是为了做一些善后工作

    a = [1,2,3]
    try:
        print(a[110])
    except Exception as e:
        print(e)
    finally:
        print('End')
    #执行结果
    list index out of range
    End
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如关闭文件:

    with语句的本质就是try…finally

    try:
        f = open('Z:/test.txt','r')
        for line in f:
            print(line.strip())
    except Exception as e:
        print('异常:',' ')
        print(e)
    finally:
        print('End')
        f.close()	#无论try是否触发异常,都会调用finally中的f.close()
    #执行结果
    Mango
    hello
    world
    End	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    抛出异常

    raise关键字

    使用 raise 关键字在代码中 “抛出异常”

    def Divide(x,y):
        if y == 0:
            raise Exception('divide zero')  #除数为0	用异常类创建一个异常对象
        return x/y
    Divide(1,0)
    #执行结果:
    Exception: divide zero
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因为我们只是抛出了异常, 并没有捕捉异常, 程序还是执行终止了(但是错误信息是我们所定义的异常信息)

    略微修改一下程序, 捕捉一下异常

    def Divide(x,y):
        if y == 0:
            raise Exception('divide zero')  #除数为0
        return x/y
    #手动捕获异常
    try:
        Divide(1,0)
    except Exception as e:
        print(e)
    #执行结果:
    divide zero
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    所谓抛出的 “异常” 其实是一个对象. 我们 Exception(‘divide zero’) 代码实际上是构造了一个异常对
    象. 这个对象的类型是Exception(Python异常的基类).


    内置异常类

    image-20220319093451914

    image-20220319093506281

    image-20220319093515710

    image-20220319093531577

    image-20220319093543452


  • 相关阅读:
    docker常用命令(云容器)
    【STL】容器与适配器(10)
    分布式搜索引擎03
    JS元编程
    c++ primer中文版第五版作业第十七章
    微服务架构师封神之路13-RabbitMQ集群与高可用|RabbitMQ clustering and HA
    DevOps2023现状报告|注重文化、以用户为中心是成功的关键
    图片懒加载
    【vue】axios封装拦截
    Guava强大的“流畅”风格比较器-Ordering的使用方法
  • 原文地址:https://blog.csdn.net/chuxinchangcun/article/details/125869341