zoukankan      html  css  js  c++  java
  • 十八. 上下文管理协议 __enter__ 和 __exit__

    十八. 上下文管理协议 __enter__ 和 __exit__

    1.什么是上下文管理协议

    上下文管理协议就是 with 语句, 为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__()__exit__()方法

    • with 对象,触发对象的__enter__的执行
    • with同一级别写代码, 脱离了with,就会执行 __exit__
    class Open:
        def __enter__(self):
            print("----->enter执行了")
            return "enter的返回值"
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("----->exit执行了")
    
    with Open() as f:  # 触发 __enter__
        print(f)
    print("---->结束")  # 触发 __exit__
    '''
    ----->enter执行了
    enter的返回值
    ----->exit执行了
    ----->结束
    '''
    

    2.exit 的三个参数

    • exc_type :异常类型
    • exc_val :异常信息
    • exc_tb :追溯信息

    with语句中代码块出现异常,则with后的代码都无法执行

    class Open:
        def __enter__(self):
            print("----->enter执行了")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("异常类型--->",exc_type)
            print("异常信息--->",exc_val)
            print("追溯信息--->",exc_tb)
            print("----->exit执行了")
    
    with Open() as f:
        print(f)
        raise AttributeError("这里设置一个异常,则下面代码不会再运行")
    
    print("---->结束")  # 这一行无法运行
    
    '''
    ----->enter执行了
    <__main__.Open object at 0x0000022E31429D08>
    异常类型---> <class 'AttributeError'>
    异常信息---> 这里设置一个异常,则下面代码不会再运行
    追溯信息---> <traceback object at 0x0000022E3142F0C8>
    ----->exit执行了
    (抛出异常) : AttributeError: 这里设置一个异常,则下面代码不会再运行
    '''
    

    3.为什么要使用上下文管理器

    • 可以自动的操作(创建/获取/释放)资源,如文件操作、数据库连接
    • 无需在使用 try...execept... 去处理异常

    如果__exit__()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

    class Open:
        def __enter__(self):
            print("----->enter执行了")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("异常类型--->",exc_type)
            print("异常信息--->",exc_val)
            print("追溯信息--->",exc_tb)
            print("----->exit执行了")
            return True
    
    with Open() as f:
        print(f)
        raise AttributeError("这里设置一个异常,但上面exit的return是True, 所以该异常被忽略")
    
    print("---->结束")  # 这一行正常运行
    
    '''
    ----->enter执行了
    <__main__.Open object at 0x000001D6CC399D08>
    异常类型---> <class 'AttributeError'>
    异常信息---> 这里设置一个异常,则下面代码不会再运行
    追溯信息---> <traceback object at 0x000001D6CC39F0C8>
    ----->exit执行了
    ---->结束
    Process finished with exit code 0
    '''
    

    4.自定义一个 open ,可以进行文件操作

    class Open:
        def __init__(self,path,mode="rt",encoding="utf-8"):
            # 拿到一个open对象,那么我们就可以借用open对象的方法,当然你也可以重写方法read(),write()等
            self.f = open(path,mode,encoding=encoding)  
    
        def __enter__(self):
            return self.f  # 返回open对象 (作用就是为了可以使用它的方法)
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            if exc_type:             # 如果不为空,说明with上下文内部出错误了
                print(exc_val)       # 打印一下错误信息
                print("错误已被忽略") # 提示一下不会结束程序
                return True          # return True 就是为了忽略错误
            self.f.close()           # 当with内部没有错误, 正常结束时进行资源清理工作(关闭文件等)
    
    with Open("test.py","rt",encoding="utf-8") as f:
        res = f.read()
        print(res)
    

    5.总结

    使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
    在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在exit中定制自动释放资源的机制,你无须再去关注这个问题

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 矩阵加法
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 乘法表
    监管只是压倒网盘业务的一根稻草,但不是主要原因(答案只有一个:成本!)
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14238441.html
Copyright © 2011-2022 走看看