• 十八. 上下文管理协议 __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中定制自动释放资源的机制,你无须再去关注这个问题

  • 相关阅读:
    Linux数据链路层的包解析
    Nmap的活跃主机探测常见方法
    甲方安全建设推进思路
    重新学习python类
    python装饰器
    记录一次奇葩渗透中的点点滴滴
    安全情报总结
    机器学习基础
    tensorflow学习笔记(四十五):sess.run(tf.global_variables_initializer()) 做了什么?
    tensorflow学习笔记(二十五):ConfigProto&GPU
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14238441.html
Copyright © 2020-2023  润新知