环境管理器

python 复制代码
#coding=utf-8

class Cooker:  # 厨师
    def open_gas(self):
        print("正在打开天然气")

    def close_gas(self):
        print("正在关闭天然气")

    def doworks(self):
        print("正在制作小甜饼")

    def __enter__(self):
        self.open_gas()
        return self  # 此对象将被 as 绑定

    def __exit__(self, exc_type, exc_value, exc_tb):
        self.close_gas()
        if exc_type is None:
            print("with语句正常退出")
        else:
            print("with语句异常退出,", exc_value)


with Cooker() as c:
    c.doworks()  # 工作中
    3/0  # ZeroDivisionError
    c.doworks()


# 正常处理流程
# c = Cooker()
# c.open_gas()
# c.doworks()
# 3/0
# c.doworks()
# c.close_gas()

这是一个上下文管理器 (context manager)的示例:

把"开燃气→做活→关燃气"这种成对资源管理 封装进 with 语句里,不管中途是正常结束 还是出异常 ,都能确保最后关掉燃气

现实对照:

  • open_gas():打开资源(文件/网络连接/锁/数据库事务...)

  • doworks():执行任务

  • close_gas():释放资源(关闭/解锁/提交或回滚...)

with 语句会调用:

  • 进入时:__enter__

  • 退出时:__exit__无论有没有异常都会调用)

执行流程图

A) 正常情况(无异常)

python 复制代码
with Cooker() as c:
    c.doworks()

流程:
__enter__  → open_gas
    ↓
块内执行   → doworks
    ↓
__exit__   → close_gas(exc_type 等参数都是 None)

B) 异常情况(比如块内 3/0)

python 复制代码
with Cooker() as c:
    c.doworks()
    3/0

流程:
__enter__  → open_gas
    ↓
块内执行   → ZeroDivisionError 抛出
    ↓
__exit__   → close_gas(收到异常信息 exc_type/ exc_value/ exc_tb)
    ↓
__exit__ 返回值决定是否"吃掉异常":
   - 返回 True  → 异常被抑制,不再往外抛
   - 返回 False/None → 异常继续向外抛

用 try/finally 等价写法

下面两段是效果等价的:

写法 1:with(推荐)

python 复制代码
with Cooker() as c:
    c.doworks()
    3/0
    c.doworks()

写法 2:手写 try/finally

python 复制代码
c = Cooker()
c.open_gas()
try:
    c.doworks()
    3/0
    c.doworks()
finally:
    c.close_gas()      # 无论是否异常,最终都会执行

差别:with 更简洁、不会忘记关资源,还能把异常信息交给 __exit__ 决定是否抑制。

控制异常

python 复制代码
    def __exit__(self, exc_type, exc_value, exc_tb):
        self.close_gas()  # 无论正常/异常退出,都先把资源关了
        if exc_type is None:
            print("with 语句正常退出")
        else:
            print("with 语句异常退出:", exc_value)

         关键点:是否抑制异常?
         若 return True ,异常被"吃掉",外面感觉不到
         若 return False/None(当前代码等价于 None),异常会继续向外抛
         这里没写 return,相当于返回 None → 不抑制异常
相关推荐
A__tao1 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
研究点啥好呢1 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
xiaotao1311 小时前
第九章:Vite API 参考手册
前端·vite·前端打包
午安~婉1 小时前
Electron桌面应用聊天(续)
前端·javascript·electron
迷藏4941 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
lifewange2 小时前
Linux ps 进程查看命令详解
linux·运维·服务器
彧翎Pro2 小时前
基于 RO1 noetic 配置 robosense Helios 32(速腾) & xsense mti 300
前端·jvm
功德+n2 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos
明日清晨2 小时前
python扫码登录dy
开发语言·python