美文网首页编程-PythonPythonpython
python 异常处理 exceptions

python 异常处理 exceptions

作者: 虐心笔记 | 来源:发表于2021-11-26 17:19 被阅读0次

    一、Excetion

    Python最强大的结构之一就是它的异常处理能力,所有的标准异常都使用类来实现。
    BaseExcetion 类是一切异常类的基类,自定义的异常类型必须直接或间接的继承自BaseExcetion类。
    在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因。


    异常相关:
    try-except: 捕获(接收)异常并进行对应处理或者终止程序。
    finally : 最终要执行的语句,常用于清理操作。
    raise : 抛出异常对象,可以抛出指定自定义异常。
    assert : 断言对象, FALSE则抛出AssertionError异常。
    with: 上下文管理


    1. 语法错误

    语法错误,也称为解析错误,初学者在学习 Python 时会经常遇到的错误类型

    impor jmespath
    
      File "C:/Users/lenovo/PycharmProjects/job/httpRunner_demo/utils/json_parser.py", line 110
        impor jmespath
                     ^
    SyntaxError: invalid syntax
    
    Process finished with exit code 1
    

    无错误提示中显示一个小“箭头”,指向检测到错误的行。错误是由(或至少检测到)箭头前面的标记引起的:
    以便知道在输入来自脚本的情况下要查找的位置。显然这里是因为import关键字错误导致的。

    2. 异常

    异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
    即使语句或表达式在语法上是正确的,当执行它时也可能导致错误。

    print(test_json)
    
    Traceback (most recent call last):
      File "C:/Users/lenovo/PycharmProjects/job/httpRunner_demo/utils/json_parser.py", line 122, in <module>
        d = jmespath.search('data.phones', test_json)
    NameError: name 'test_json' is not defined
    
    Process finished with exit code 1
    

    异常的抛出机制:

    • 如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).
    • 要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。
    • 如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。
    • 错误消息的最后一行指示发生了什么。异常有不同的类型,类型作为消息的一部分打印:上面的异常类型是 NameError。作为异常类型打印的字符串是发生的内置异常的名称。用户定义的异常可能会瞎定义。

    注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。

    3. 处理异常 try...except

    捕捉异常可以使用try/except语句。try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
    ps:如果你不想在异常发生时结束你的程序,只需在try里捕获它。

    try:
        10/0
    except Exception as e:
        print(f'print("Oops!  {e}  Try again...")')
    
    Oops!  division by zero  Try again...
    
    Process finished with exit code 0
    
    • 当开始一个try语句后,python就在当前程序的上下文中作标记,异常出现时就可以回到这里。
    • try子句先执行,接下来会发生什么依赖于执行时是否出现异常。首先,try 子句(try和 except关键字之间的语句)被执行。
    • 如果当 try 后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的 except 子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
    • 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
    • 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。
      一条try语句可能有多个except 子句,以指定不同异常的处理程序。最多会执行一个处理程序。处理程序只处理在相应的try 子句中发生的异常,而不是在同一try语句的其他处理程序中。一个except子句 可以将多个异常命名为一个带括号的元组
      except (RuntimeError, TypeError, NameError): pass

    4. 引发异常raise

    直接抛出指定的异常: raise [Exception [, args [, traceback]]]

    >>> raise NameError('Hi There')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: Hi There
    
    

    唯一参数 raise 指示要引发的异常。这必须是异常实例或异常类(派生自 的类Exception)。
    如果传递了一个异常类,它将通过不带参数调用其构造函数来隐式实例化,如果您需要确定是否引发了异常但不打算处理它,则该raise语句的更简单形式直接抛。

    6. 用户定义的异常

    通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。
    注意:自定义异常只能由自己抛出,python解释器无法识别用户自定义异常

    class CustomError(Exception):
        def __init__(self, error):
            super().__init__(self)
            self.error_info = error
    
        def __str__(self):
            return self.error_info
    
        def __repr__(self):
            return self.error_info
    
    
    if __name__ == '__main__':
        try:
            raise CustomError('! CustomError')
        except CustomError as e:
            print(e)
            raise 
    
    Traceback (most recent call last):
    ! CustomError
      File "C:/Users/lenovo/PycharmProjects/job/httpRunner_demo/utils/json_parser.py", line 119, in <module>
        raise CustomError('! CustomError')
    __main__.CustomError: ! CustomError
    
    Process finished with exit code 1
    

    下面参考 httprunner2 框架中对 exceptions.py 的封装

    class MyBaseFailure(Exception):
        """ failure type exceptions, these exceptions will mark test as failure """
        pass
    
    
    class ParseTestsFailure(MyBaseFailure):
        pass
    
    
    class ValidationFailure(MyBaseFailure):
        pass
    
    
    class ExtractFailure(MyBaseFailure):
        pass
    
    8. 上下文管理操作

    with表达式其实是try...finally的简写形式。但是又不是全相同。

    上下文管理协议(Context Management Protocol):包含方法 enter()和exit(),支持该协议的对象要实现这两个方法。
    上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了enter()和exit()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。

    表达式:with EXPR as VAR : SUITE

    • 执行EXPR,生成上下文管理器context_manager,获取上下文管理器的exit()方法,并保存起来用于之后的调用,调用上下文管理器的enter()方法.
    • 如果使用了as子句,则将enter()方法的返回值赋值给as子句中的 VAR 执行 BLOCK 中的表达式.
    • 不管是否执行过程中是否发生了异常,执行上下文管理器的exit()方法,exit()方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句break/continue/return,则以None作为参数调用exit(None, None, None).
    • 如果执行过程中出现异常则使用sys.exc_info得到的异常信息为参数调用exit(exc_type, exc_value, exc_traceback)
      出现异常时,如果exit(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用做法;如果返回True,则忽略异常,不再对异常进行处理。
    class SqlHelper(object):
        def __init__(self, config):
            self.connect = pymysql.connect(config)
            self.connect.autocommit(True)
    
        def __enter__(self):
            self.cursor = self.connect.cursor(cursor=pymysql.cursors.DictCursor)
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.cursor.close()
            self.connect.close()
            
    if __name__ == '__main__':
        # 上下文管理方式执行
        with SqlHelper(config) as db:
            result = db.operation(sql)
            print(result)
    

    相关文章

      网友评论

        本文标题:python 异常处理 exceptions

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