用好 Python 上下文管理器:contextlib 让你少写一半 with 代码
用好 Python 上下文管理器contextlib 让你少写一半 with 代码with语句几乎每个 Python 程序员每天都在用打开文件、加锁、连接数据库。但很多人只停留在with open(...)这个层面一旦需要自己封装资源或复用一段进入/退出逻辑就手写__enter__和__exit__甚至干脆放弃用with、裸写try/finally。这篇文章讲清contextlib标准库里的几个实用工具让你把资源管理代码写得更短、更安全。一、先明确一个事实with 不等于 openwith语句本质上是协议不是文件专用语法。一个对象只要实现了__enter__和__exit__或者被contextlib包装就能用with管理。理解这一点后很多场景立刻开阔起来withopen(data.txt,r,encodingutf-8)asf:textf.read()上面这行代码解释器实际执行的是fopen(data.txt,r,encodingutf-8)try:textf.read()finally:f.close()with的价值在于无论with块里正常结束还是抛异常退出逻辑close都会被保证执行。手写try/finally也能做到但容易漏、容易忘with让这件事变成强制。二、场景 1同一个进入/退出逻辑要复用假设你在多个地方需要临时修改环境变量用完再改回来。最朴素的写法是importos oldos.environ.get(MY_VAR)os.environ[MY_VAR]temporarytry:do_something()finally:ifoldisNone:os.environ.pop(MY_VAR,None)else:os.environ[MY_VAR]old这段代码一旦要在两三个函数里重复就很烦。用contextmanager装饰器可以把它封装成可复用的上下文管理器fromcontextlibimportcontextmanagerimportoscontextmanagerdeftemp_env_var(name:str,value:str):临时设置环境变量退出时恢复原值。oldos.environ.get(name)os.environ[name]valuetry:yieldfinally:ifoldisNone:os.environ.pop(name,None)else:os.environ[name]old用法withtemp_env_var(MY_VAR,temporary):print(os.environ[MY_VAR])# temporaryprint(os.environ.get(MY_VAR))# 恢复到原来的值或不存在关键点有两个yield前面是进入逻辑后面是退出逻辑。finally保证退出逻辑一定执行——即使with块里抛了异常yield之后的finally也会跑。陷阱提醒contextmanager装饰的函数里try一定要把yield包住否则with块里的异常不会触发你的清理逻辑。三、场景 2临时换工作目录chdir是全局生效的容易让后续代码不知道自己身在哪个目录。用上下文管理器把目录切换限制在一个作用域内是常见且实用的做法fromcontextlibimportcontextmanagerimportoscontextmanagerdefworking_directory(path:str):临时切换到指定目录退出时切回。oldos.getcwd()os.chdir(path)try:yieldfinally:os.chdir(old)这样切目录这件事就变成了和文件一样清晰的作用域withworking_directory(/tmp):print(当前目录,os.getcwd())print(回到,os.getcwd())这个模式在构建脚本、测试隔离里特别常用。四、场景 3多个上下文管理器一起用有些资源是嵌套的比如同时打开两个文件做合并或者同时持有两把锁。可以并列写withopen(a.txt)asfa,open(b.txt)asfb:text_afa.read()text_bfb.read()也可以配合ExitStack动态地管理运行时才知道数量的上下文管理器数组。ExitStack是contextlib里的一个进阶工具能把你 push 进去的上下文管理器统一退出fromcontextlibimportExitStack files[a.txt,b.txt,c.txt]withExitStack()asstack:handles[stack.enter_context(open(f))forfinfiles]forhinhandles:print(h.readline().rstrip())# 退出 with 后所有文件句柄都会被自动 closeExitStack尤其适合上下文管理器的数量和内容在运行时才确定的场景比如动态加载一批插件、批量建立数据库连接等。五、场景 4关闭一个本不是上下文管理器的对象closing能把一个只提供close()方法、却没有实现上下文管理器协议的对象包装成可用with的对象fromcontextlibimportclosingimportsqlite3 connsqlite3.connect(:memory:)withclosing(conn):cursorconn.cursor()cursor.execute(CREATE TABLE t (id INTEGER))# 退出后 conn 已经 close注意sqlite3.Connection本身也支持with但它的with并不会自动关闭连接只是提交/回滚事务。所以如果你确实想用完就关closing是更明确的表达。这一点容易踩坑值得单独记住。六、什么时候不该用 contextmanagercontextmanager适合做一次性的进入/退出。如果你需要一个可复用、可迭代、带状态的上下文对象比如可以多次进入、内部维护复杂状态那还是老老实实写类、实现__enter__和__exit__更清晰。contextmanager是轻量便捷不是万能替代。小结with是通用协议不是open专用核心价值是保证退出逻辑执行。contextmanager把进入/退出封装成可复用函数yield前后分别对应两者try必须包住yield。ExitStack适合运行时动态管理的多上下文closing适合包装只有close()的对象。需要复杂状态管理时回到类 __enter__/__exit__。延伸阅读官方文档 contextlib — Utilities for with-statement contexts以及 PEP 343 了解with语句的设计背景。

相关新闻

自动化运维-从零开始编写ansible剧本(二)

自动化运维-从零开始编写ansible剧本(二)

前言 前述文章自动化运维-ansible常用模块详解已经详细介绍过ansible 常用模块的Ad-hoc命令实现方式,适合执行 临时性、简单的任务;而使用较多的方式是通过ansible playbook实现多任务执行,无需重复多次输入命令。 本篇文章将通过剧本的方式…

2026/8/23 23:55:53 阅读更多 →
GEO常见误区:以逸阳女裤为例看做了内容不等于被AI引用

GEO常见误区:以逸阳女裤为例看做了内容不等于被AI引用

核心摘要 服装品牌做GEO,最容易踩的坑是“以为发了文章就完事”。逸阳女裤作为可溯源案例,恰好能说明哪些做法有效、哪些只是自我安慰。本文列四个常见误区,帮服装老板少走弯路。河南新流量文化传播有限公司的GEO系统,是一套覆盖…

2026/8/23 23:54:52 阅读更多 →
模拟案例:兰州建材实施异常怎么排查?模拟环境与验证步骤

模拟案例:兰州建材实施异常怎么排查?模拟环境与验证步骤

围绕建材,先明确读者需要解决的具体问题,再依次核对适用条件、事实依据、验证方法和不适用边界,不能用宣传结论代替可复查证据。## 案例性质本文是一个基于典型建材业务场景的模拟案例,旨在说明健康墙板从需求确认到落地验收的全过…

2026/8/23 23:54:52 阅读更多 →

最新新闻

Java面试必考技术点解析:JVM、Spring、分布式与并发编程

Java面试必考技术点解析:JVM、Spring、分布式与并发编程

1. 为什么这些技术点成为面试必考题在近五年的Java技术岗位招聘中,JVM、Spring框架、分布式系统和并发编程这四大领域的考察频率持续居高不下。根据某头部招聘平台2023年的数据统计,中级以上Java开发岗位的面试中,这四个方向的问题出现率分别…

2026/8/24 5:07:42 阅读更多 →
机器人关节运动极限问题:从原理到ROS/MoveIt!的排查与优化实践

机器人关节运动极限问题:从原理到ROS/MoveIt!的排查与优化实践

最近在调试机器人运动控制时,反复遇到一个棘手问题:机器人腰部关节在特定姿态下会突然停止或报错,提示“运动极限”或“关节超限”。排查后发现,这不仅仅是简单的参数设置问题,而是涉及机器人运动学、关节物理约束、控…

2026/8/24 5:07:42 阅读更多 →
C# ToList()源码深度解析:IIListProvider性能优化机制

C# ToList()源码深度解析:IIListProvider性能优化机制

1. 为什么一个看似简单的ToList()值得深挖源码你写过多少次list.Where(x > x > 0).ToList()?我数不清了。它像呼吸一样自然,像Console.WriteLine一样基础——直到某天,你在性能分析器里看到它在热路径上占了8%的CPU时间,而你…

2026/8/24 5:07:42 阅读更多 →
DeepSeek V4 Vision多模态模型API调用实战指南

DeepSeek V4 Vision多模态模型API调用实战指南

如果你正在寻找一个既能看懂图片内容,又能理解复杂图表,还能帮你写代码的多模态AI模型,那么DeepSeek最新推出的V4 Vision模型绝对值得你立刻关注。这不仅仅是又一个“看图说话”的工具,它真正解决的是开发者、产品经理和数据分析师…

2026/8/24 5:07:42 阅读更多 →
洛谷 P7911:[CSP-J 2021 T3] 网络连接 ← 字符串 + unordered_map + vector

洛谷 P7911:[CSP-J 2021 T3] 网络连接 ← 字符串 + unordered_map + vector

【题目来源】 https://www.luogu.com.cn/problem/P7911 【题目描述】 TCP/IP 协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。 在本问题中,计算机分为两大类:服务机&#…

2026/8/24 5:07:42 阅读更多 →
Apktool 安装配置:从下载到跑通第一条命令(完整指南)

Apktool 安装配置:从下载到跑通第一条命令(完整指南)

Apktool 安装配置:从下载到跑通第一条命令(完整指南) 【免费下载链接】Apktool A tool for reverse engineering Android apk files 项目地址: https://gitcode.com/GitHub_Trending/ap/Apktool Apktool 是一款用于逆向 Android APK 文…

2026/8/24 5:06:42 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →