美文网首页
Python中的异常处理

Python中的异常处理

作者: welder77 | 来源:发表于2022-07-17 07:16 被阅读0次

    今天我们来说说Python的异常处理,在说异常处理之前我们先来了解下,Python中有哪些常见的错误类型。

    在Python中,当代码中有错误时,程序默认会在终端中将错误类型和原因打印出来:

    以下是Python中一些常用错误类型:

    1. SyntaxError(语法错误)
    print('函数最后没有加小括号'
    
    #运行程序后报错 SyntaxError: unexpected EOF while parsing
    
    1. NameError(名称错误)
    if not_defined > 0:
        print("NOk")
    
    #运行程序后报错 NameError: name 'not_defined' is not defined
    
    1. LookupError (查询错误)
    li = [1, 2, 3]
    li[1024]
    
    #运行程序后报错 IndexError: list index out of range
    
    di = {'code':'JD', 'price':42}
    di['CEO']
    
    #运行程序后报错 KeyError: 'CEO'
    
    1. ArithmeticError(运算错误)
    1/0
    #运行程序后报错 ZeroDivisionError: division by zero
    
    1. TypeError(类型错误)
    days = 365 + '1004'
    #运行程序后报错 TypeError: unsupported operand type(s) for +: 'int' and 'str'
    
    1. ValueError(值错误)
    int('永远有多远')
    #运行程序后报错 ValueError: invalid literal for int() with base 10: '永远有多远'
    
    1. AttributeError(属性错误)
    a = 1
    a.append(2)
    #运行程序后报错 AttributeError: 'int' object has no attribute 'append'
    
    1. OSError(系统错误)
    f = open('No Such File.txt')
    #运行程序后报错 FileNotFoundError: [Errno 2] No such file or directory: 'No Such File.txt'
    
    1. ImportError(导入错误)
    from numpy import sqr
    #运行程序后报错 ImportError: cannot import name 'sqr' from 'numpy'
    
    1. ModuleNotFoundError(未找到模块错误)
    import numq
    #运行程序后报错 ModuleNotFoundError: No module named 'numq'
    
    1. StopIteration(迭代停止错误)
    i = iter([1,2,3])
    print(next(i))
    print(next(i))
    print(next(i))
    print(next(i))
    
    #运行程序后报错 StopIteration:
    

    看到这里,你一定会有一个疑问,Python怎么有那么多不同的错误分类呀,我都需要一一全都记下来吗?
    就个人学习的经验来说,可以先以了解为主,在后续实际应用中,记住与自己代码相关的错误类型即可。

    随后,我们来说说今天的主题,异常处理,我们首先需要明白的是,我们无法完全阻止错误发生,但是可以提前预防以至于程序不会崩溃。这个提前预防的动作称为异常处理(exception handling),异常处理就是为了防患于未然。

    从以上的错误类型我们知道,Python 在程序报错时会返回错误类型和信息,我们可以提前去捕捉我们能预计到的及无法预计到的错误类型,并做相应的处理。

    接下来,我们来介绍几种典型的异常处理方式:

    1. Try-Except
    异常处理最常见的语句就是 try-except 组合,细分又有三种类型:

    (1) 知道错误但不确定类型,用 except Exception


    except Exception

    例子:

    def divide(a, b):
        try:
            c = a / b
            print(f"Result = {c:.4f}.")
        except Exception as err:
            print(f'因子是0,无法进行相除! 具体错误为:{err}')
    
    divide(10, 0) #因子是0,无法进行相除! 具体错误为:division by zero
    

    这里解释下:
    except Exception as err 的含义是将任意异常定义为一个err对象,后续可将err转为字符串打印出来,程序会打印错误原因,如需同时打印错误类型和原因,则需要使用repr(err)。

    (2)知道错误而且确定类型,用 except some_exception


    except some_exception

    例子:

    def divide(a, b):
        try:
            c = a / b
            print(f"Result = {c:.4f}.")
        except ZeroDivisionError:
            print(f'因子是0,无法进行相除! ')
    
    divide(10, 0) #因子是0,无法进行相除!
    

    (3)知道错误而且有多个错误
    用多个 except

    用 except (exc_1, exc_2, ... exc_n)


    多个错误

    例子:

    def divide(a, b):
        try:
            c = a / b
            d = cc + 1
            print(f"Result = {c:.4f}.")
        except ZeroDivisionError:
            print('因子是0,无法进行相除!')
        except NameError:
            print('变量名未定义!')
    
    divide(10, 2) #变量名未定义!
    divide(10, 0) #因子是0,无法进行相除!
    

    有时,我们也可以对多个错误进行统一处理,比如:

    except (ZeroDivisionError,NameError):
        print('Error occurred!')
    

    实际工作中,我们也会遇到不同错误类型,做差分处理的情况,比如控制机械手臂时,如遇到sockets连接丢失的异常时,可以做重连操作,遇到控制指令返回超时的异常可以做提示重试的处理,其他任意错误则终止机械手臂的控制,这样代码既智能又安全。

        try:
            动作
        except SocketsError:
            重连处理
        except NoResponseError:
            提示重试处理
        except Exception:
            停止控制
    
    p.s 以上SocketsError和NoResponseError为自建的错误类型,Exception为所有其他异常即所有其他错误类型,程序出错时会进入对应的一种错误类型中去。
    

    2. Try-Except-Else

    Try-Except-Else

    首先要明确的是,else 语句是可有可无的。如果存在,则 else 语句应始终在 except 语句之后。

    当 try 语句下的代码未发生异常时,才会执行 else 子句下的代码。
    当 try 语句下的代码中发生异常,则 except 语句将处理异常,else 语句将不会执行。

    个人认为,Try-Except-Else的存在感并不是很强,因为完全可以通过在try的最后,添加相应的代码来实现同样的功能。

    3. Try-Except-Else-Finally

    Try-Except-Else-Finally

    无论是否发生异常,finally 语句始终在 try 语句运行之前执行。

    在实际工作中,finally 是非常有用的。
    比如调用音频采集卡时,我们希望无论采集成功或异常失败时,最终程序都会做一次停止采集的动作来释放资源。这时我们就可以将停止采集的动作放在finally语句中。

    4. Raise Exception
    除了上面处理异常的操作之外,我们还可以用 raise 关键词“抛出”异常,抛出异常可分为两类:

    (1) 抛出内置异常
    在下例中,如果输入非整数,我们抛出一个 ValueError(注意这是 Python 里面内置的异常对象),顺带打印“This is not a positive number”的信息。

    try:
        a = int(input("Enter a positive integer: "))
        if a <= 0:
            raise ValueError("That is not a positive number!")
    except ValueError as err:
        print(err)
    

    (2) 抛出自定义异常
    这里我们先需要了解如何自定义异常:
    在 Python 里,所有异常都是 Exception 的子类,因此在定义其类时需要进行继承。
    class Error(Exception):
    class your_exception(Error):

    具体代码如下。

    class Error(Exception):
        pass
    
    class NegativePortfolioValueWarning(Error):
        def __init__(self, expression, message):
            self.expression = expression
            self.message = message
    

    随后,我们就可以在代码中,抛出自定义的NegativePortfolioValueWarning异常了。

    def portfolio_value(last_worth, current_worth):
        if last_worth < 0 or current_worth < 0:
            raise ValueError('Negative worth!')
        value = current_worth - last_worth
        if value < 0:
            raise NegativePortfolioValueWarning(
            'NegativePortfolioValueWarning', \
            'Negative return. Take a look!')
    

    总结,Python中对不同错误类型做了细分且分类非常多,实际代码调试过程中,我们可以通过打印的方式将错误类型和原因打印出来,以便让程序继续运行的前提下了解错误信息。
    对于不同的错误类型,我们可以做差分处理,以便让程序容错性更好且更智能。
    对于自己编写程序的一些特殊异常。我们可以自建错误类型,并通过raise抛出。

    相关文章

      网友评论

          本文标题:Python中的异常处理

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