环境管理器

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 → 不抑制异常
相关推荐
Doro再努力1 天前
【Linux操作系统06】深入理解权限掩码与粘滞位
linux·运维·服务器
wdfk_prog1 天前
[Linux]学习笔记系列 -- [drivers][dma]stm32-dma
linux·笔记·学习
mzhan0171 天前
[Linux] vdso 32bit vs 64bit
linux·运维·服务器
tao3556671 天前
【用AI学前端】HTML-02-HTML 常用标签(基础)
前端·html
旖旎夜光1 天前
Linux(13)(上)
linux·网络
忧郁的橙子.1 天前
26期_01_Pyhton linux基本命令
linux·运维·服务器
Sagittarius_A*1 天前
形态学与多尺度处理:计算机视觉中图像形状与尺度的基础处理框架【计算机视觉】
图像处理·人工智能·python·opencv·计算机视觉
2601_949532841 天前
Psello HTML Template: A Developer‘s Deep-Dive Review and Guide - Download Free
前端·windows·html·seo·wordpress·gpl
CappuccinoRose1 天前
CSS前端布局总指南
前端·css·学习·布局·flex布局·grid布局·float布局
m0_561359671 天前
使用PyQt5创建现代化的桌面应用程序
jvm·数据库·python