Python上下文管理协议 __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("---->结束")  # 这一行正常运行
#Python小白学习交流群:725638078
'''
----->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)
__enter__方法是上下文管理协议中的一个方法,用于在进入with语句块之前执行一些操作。在引用\[1\]中的例子中,Test类实现了__enter__方法,在进入with语句块之前打开了一个文件,并返回了文件对象。这样,在with语句块中可以使用这个文件对象进行操作。\[1\] __enter__方法的返回值可以通过as关键字绑定到一个变量上,以便在with语句块中使用。在引用\[2\]的例子中,Open类的__enter__方法返回了一个字符串"enter的返回值",在with语句块中可以通过变量f来引用这个返回值。\[2\] 使用上下文管理器的好处是可以确保资源的正确释放。在引用\[3\]的例子中,如果with语句块中出现异常,__exit__方法会被调用来处理异常并释放资源。这样可以避免资源泄漏。\[3\] 总之,使用上下文管理器可以简化资源的管理,确保资源的正确释放,并提高代码的可读性和可维护性。 #### 引用[.reference_title] - *1* [python的with和__enter__ 、 __exit__](https://blog.csdn.net/weixin_33851177/article/details/86028395)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Python上下文管理协议 __enter__ 和 __exit__](https://blog.csdn.net/Python_222/article/details/129880336)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值