Python学习

作者: 逛逛_堆栈 | 来源:发表于2021-04-04 01:05 被阅读0次

    第九天

    今天我们来说下Python中的异常,以及如何去处理异常。我们在程序编码中难免会碰到异常,今天我们就要来简要说明什么是异常,如何处理异常。

    1、异常的定义

    不论是Python语言、Java语言以及其他任何语言,程序在执行的过程中难免会产生的错误,这些错误都可以称之为异常。比如列表索引越界、打开不存在的文件等。
    就如同下面两行代码:

    print(str1)
    # name 'str1' is not defined
    open('error.txt','r')
    # No such file or directory: 'error.txt'
    

    2、异常处理

    程序中出现异常是难免的,发生异常时我们需要捕获处理它,否则程序会终止执行。
    如下代码:

    #控制台输入两个数字 求商
    print('程序开始')
    num1 = int(input('请输入除数'))
    num2 = int(input('请输入被除数'))
    print(str(num1)+'除以'+str(num2)+'的结果是',str(num1/num2))
    print('程序结束')
    

    上述这段代码其实就是存在问题的,比如我在获得数字num1的时候输入的内容不可以转换为int(比如你输入wasd),这个时候就出现异常了。
    ValueError: invalid literal for int() with base 10: 'wasd'
    其实就是将非数字字符串转换为整型出现的异常;
    如果你在获得num2的时候,如果输入了0也会出现异常,
    ZeroDivisionError: division by zero
    其实就是除以0的原因导致的。
    并且我们发现上述两种异常任何一种异常出现,我们的程序就停止了,并且程序没有往下执行,因为我们在控制台看不到最后一行print的输出。
    这时候就需要我们异常处理了。

    2.1、异常类

    在Python中,所有异常都是基类Exception的成员,它们都定义在exceptions模块中。
    如果这个异常对象没有进行处理和捕捉,程序就会用所谓的回溯(traceback,一种错误信息)终止执行,这些信息包括错误的名称(例如NameError)、原因和错误发生的行号。下面简单说下我们经常遇见的几个异常:
    1、NameError
    尝试访问一个未声明的变量,会引发NameError。

    print(str1)
    # NameError: name 'str1' is not defined
    

    2、ZeroDivisionError
    当除数为零的时候,会引发ZeroDivisionError异常。

    a = 10/0
    print(a)
    # ZeroDivisionError: division by zero
    

    **3、SyntaxError **
    当解释器发现语法错误时,会引发SyntaxError异常。

    a = 10
    if a == 10
        print('宾果!')
    # SyntaxError: invalid syntax
    

    4、IndexError
    当使用序列中不存在的索引时,会引发IndexError异常。

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

    5、KeyError
    当使用映射中不存在的键时,会引发KeyError异常。

    mydict = {'name':'张三','age':18}
    address = mydict['address']
    print(address)
    # KeyError: 'address'
    

    **6、FileNotFoundError **
    试图打开不存在的文件时,会引发FileNotFoundError。

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

    7、AttributeError
    当尝试访问未知对象属性时,会引发AttributeError异常。

    class Settings():
       def _init_(self):
           self.scren_width=1200
           self.screen_height=800
           self.bg_color=(230,230,230)
    if __name__ == '__main__':
       a = Settings()
       print(a.scren_width)
    # AttributeError: 'Settings' object has no attribute 'scren_width'
    

    2.2、异常处理

    在python中,try-except语句定义了监控异常的一段代码,并提供了处理异常的机制。

    1、捕获指定异常

    try:
            # 可能会出现异常的语句块
    except <异常种类>:
            # 异常处理代码
    
    print('程序开始')
    try:
        a = 10/0
        print(a)
    except ZeroDivisionError as e:
        print('捕获异常-零不可以是除数',e)
    print('程序继续执行')
    # 程序开始
    # 捕获异常-零不可以是除数 division by zero
    # 程序继续执行
    

    注意,exception后捕获的异常必须和try代码块中出现的异常种类一致,才可以捕获,否则依然会出现异常,影响其后代码的执行。

    print('程序开始')
    try:
        a = 10/0
        print(a)
    except FileNotFoundError as e:
        print('捕获异常-文件找不到',e)
    print('程序继续执行')
    # ZeroDivisionError: division by zero
    

    2、捕获多个异常

    捕获多个异常有两种方式,第一种是一个except同时处理多个异常,不区分优先级。

    try:
         # 可能会出现异常的语句块
    except (<异常名1>, <异常名2>, ...): 
          # 异常处理代码
    
    print('程序开始')
    try:
       num1 = int(input('请输入除数'))
       num2 = int(input('请输入被除数'))
       print(str(num1)+'除以'+str(num2)+'的结果是',str(num1/num2))
    except (ZeroDivisionError,ValueError):
       print('出现异常了')
    print('程序继续执行')
    

    还有第二种方式,是区分优先级的。

    try:
            # 可能会出现异常的语句块
    except <异常种类1>:
            # 异常处理代码1
    except <异常种类2>:
            # 异常处理代码2
    except <异常种类3>:
            # 异常处理代码3
    
    print('程序开始')
    try:
       num1 = int(input('请输入除数'))
       num2 = int(input('请输入被除数'))
       print(str(num1)+'除以'+str(num2)+'的结果是',str(num1/num2))
    except ZeroDivisionError as e1:
       print('出现异常了',e1)
    except ValueError as e2:
       print('出现异常了',e2)
    print('程序继续执行')
    

    3、异常中的else

    如果try语句没有捕获到任何的错误信息,就不再执行任何except语句,而是会执行else语句。

    try:
            # 可能会出现异常的语句块
    except <异常种类1>:
            # 异常处理代码1
    except <异常种类2>:
            # 异常处理代码2
    except <异常种类3>:
            # 异常处理代码3
    else:
        # try语句中没有异常则执行此段代码
    
    import  os
    print('程序开始执行')
    try:
        wfile = open('2.txt','w',encoding='utf-8')
        wfile.write('这是测试文件写入的内容')
    except IOError as e:
        print('IO异常',2)
    else:
        print('内容写入成功')
        wfile.close()
    print('程序继续执行')
    # 程序开始执行
    # 内容写入成功
    # 程序继续执行
    

    4、捕获所有的异常

    当程序中出现大量异常时,捕获这些异常是非常麻烦的。这时,我们可以在except子句中不指明异常的类型,这样,不管发生何种类型的异常,都会执行except里面的处理代码。

    print('程序开始')
    try:
       num1 = int(input('请输入除数'))
       num2 = int(input('请输入被除数'))
       print(str(num1)+'除以'+str(num2)+'的结果是',str(num1/num2))
    except:
       print('出现异常了')
    print('程序继续执行')
    

    5、终止行为(finally)

    在程序中,无论是否捕捉到异常,都必须要执行某件事情,例如关闭文件、释放锁等,这时可以提供finally语句处理。通常情况下,finally用于释放资源。

    str = 'hello python'
    try:
        a = int(str)
    except IndexError as e1:
        print('出现异常',e1)
    except KeyError as e2:
        print('出现异常',e2)
    except ValueError as e3:
        print('出现异常',e3)
    else:
        print('try内没有异常')
    finally:
        print('无论异常与否,都会执行我')
    

    3、raise语句

    python是否可以在程序的指定位置手动抛出一个异常?答案是肯定的,python 允许我们在程序中手动设置异常,使用 raise 语句即可。类似Java中的throw。
    语法:raise [exceptionName [(reason)]]
    其中,用 [] 括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述。如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息。
    简而言之就是使用raise语句能显示地触发异常。
    格式如下:
    1、raise 异常类名 引发指定异常类的实例
    2、raise 异常类对象 引发指定异常类的实例
    3、raise 重新引发刚刚发生的异常

    3.1、使用类名引发异常

    print('程序开始执行')
    try:
        a = input('请输入一个数字')
        #判断用户输入的是否为数字
        if(not a.isdigit()):
            raise ValueError("输入的必须是数字") #人为扔出异常
    except ValueError as e:
        print("引发异常:",repr(e))
    print('程序继续执行')
    # 程序开始执行
    # 请输入一个数字wasd
    # 引发异常: ValueError('输入的必须是数字')
    # 程序继续执行
    

    3.2、使用异常类的实例引发异常

    print('程序开始执行')
    try:
        a = input('请输入一个数字')
        #判断用户输入的是否为数字
        if(not a.isdigit()):
            err = ValueError()
            raise err
    except ValueError as e:
        print("引发异常:",repr(e))
    print('程序继续执行')
    

    3.3、raise传递异常

    不带任何参数的raise语句,可以再次引发刚刚发生过的异常,作用就是向外传递异常。

    print('程序开始执行')
    try:
        a = input('请输入一个数字')
        #判断用户输入的是否为数字
        if(not a.isdigit()):
            raise ValueError("输入的必须是数字")
    except ValueError as e:
        print("引发异常:",repr(e))
        raise
    print('程序继续执行')
    # ValueError: 输入的必须是数字
    

    4、assert语句

    assert语句又称作断言,指的是期望用户满足指定的条件。
    当用户定义的约束条件不满足的时候,它会触发AssertionError异常,所以assert语句可以当做条件式的raise语句。
    assert语句格式如下:
    assert 逻辑表达式,data
    相当于:
    if not 逻辑表达式:
    raise AssertionError(data)
    assert后面紧跟一个逻辑表达式,相当于条件。Data通常是一个字符串,当条件为false时作为异常的描述信息。

    print('程序开始执行')
    a = int(input('请输入除数'))
    assert a != 0,'除数不可以为0'
    # AssertionError: 除数不可以为0
    

    5、自定义异常

    python允许我们自定义异常,只需要两步:
    1、创建一个继承Exception类的子类,就是自定义异常类。
    2、当遇到自己设定的错误时,使用raise语句抛出自定义的异常。

    #自定义异常类
    class MyErr(Exception):
        def __init__(self,args):
            self.args = args
    #触发自定义异常
    if __name__ == '__main__':
        print('程序开始执行')
        try:
            raise MyErr('这是我自定义的异常')
        except MyErr as e:
            print('出现的异常为',e.args)
    

    6、总结

    这次主要针对Python的异常进行介绍,包括异常类、抛出和捕捉系统内置的异常、抛出和捕捉自定义异常,大家应该深入了解了异常产生的原理,并知道如何在程序中运行它们。

    相关文章

      网友评论

        本文标题:Python学习

        本文链接:https://www.haomeiwen.com/subject/wwlhkltx.html