环境管理器

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 → 不抑制异常
相关推荐
2601_951615209 分钟前
网站模板 网站网页模板下载
前端·网络·html
外收内放20 分钟前
Python基础语法练习题(69)
开发语言·python
TomEval24 分钟前
【测AI】第11篇:深度学习基础 —— 神经网络是怎么工作的
人工智能·python·深度学习·神经网络·机器学习·aigc
zhang-ge27 分钟前
python包和项目管理器uv在ubuntu下的安装与使用
开发语言·python·uv
for_ever_love__38 分钟前
LangChain 降级、重试与超时:让服务在模型抽风时还能用
python·自然语言处理·langchain·agent·超时·重试·with_retry
GeW38 分钟前
以Linux为基、数据库为核:新质生产力路线图下的企业架构升级
linux
酷炫码神43 分钟前
Day 1|HTML5:一个商城首页的骨架,从 DOCTYPE 到语义化
前端·html·html5
MoRanzhi12031 小时前
第 8 篇 · 机器学习建模与实验评估:建模流程与对照实验
python·机器学习·scikit-learn·模型评估·交叉验证·shap·消融实验
忆挽篱笙歌1 小时前
进程的状态
linux·ubuntu
棉猴1 小时前
玩游戏学Python9-算术运算符应用1
python·游戏·pygame·玩游戏·游戏编程