Python yield 的正确使用

定义上下文管理器

python 复制代码
import contextlib

@contextlib.contextmanager
def open_managed_file(filepath, mode='r'):
    """
    一个上下文管理器,用于安全地打开和关闭文件。
    """
    f = None
    try:
        # 1. 资源获取/进入上下文 (__enter__)
        f = open(filepath, mode)
        print(f"[ENTER]: 成功打开文件 '{filepath}',模式为 '{mode}'")
        
        # 2. 暂停并返回资源
        # yield 后面的值 (f) 将被绑定到 with ... as 后的变量上
        yield f 

    except FileNotFoundError:
        print(f"[EXIT]: 错误!文件 '{filepath}' 未找到。")
        raise
        
    finally:
        # 3. 资源清理/退出上下文 (__exit__)
        if f:
            print(f"[EXIT]: 正在关闭文件 '{filepath}'...")
            f.close()

使用 with 语句进行文件操作

我们首先创建一个临时文件供读取,然后使用上下文管理器。

python 复制代码
# 1. 创建一个测试文件
TEST_FILE = "test_config.txt"
with open(TEST_FILE, "w") as temp:
    temp.write("Setting A=10\n")
    temp.write("Setting B=20\n")

print("-" * 30)

# 2. 使用上下文管理器读取文件
try:
    with open_managed_file(TEST_FILE, 'r') as file_handle:
        # 在 with 块内,file_handle 就是 open_managed_file 中 yield 返回的文件对象
        content = file_handle.read()
        print("\n[WITH BLOCK]: 文件内容读取完成。")
        print("---")
        print(content.strip())
        print("---")

    # 当 with 块结束时,文件已被自动关闭 (执行了 finally 块)
    print("上下文管理块正常退出。")

except FileNotFoundError:
    print("程序捕获到文件未找到的错误。")

运行结果(会显示整个流程):

yaml 复制代码
------------------------------
[ENTER]: 成功打开文件 'test_config.txt',模式为 'r'

[WITH BLOCK]: 文件内容读取完成。
---
Setting A=10
Setting B=20
---
[EXIT]: 正在关闭文件 'test_config.txt'...
上下文管理块正常退出。

异常处理演示

即使在 with 块内部发生异常,finally 块也会确保文件被关闭:

python 复制代码
print("-" * 30)
print("演示异常情况下的清理:")

try:
    with open_managed_file(TEST_FILE, 'r') as file_handle:
        print("[WITH BLOCK]: 尝试读取文件...")
        
        # 故意制造一个错误(例如,除以零)
        result = 10 / 0 
        print(f"这个不会被打印: {result}")
        
except ZeroDivisionError:
    # 外部捕获了异常,但文件已经在退出时关闭了
    print("\n[外部]: 成功捕获到 ZeroDivisionError。")
    # 注意,即使发生了异常,open_managed_file 内部的 finally 块也会先执行。

异常运行结果(显示清理优先于异常捕获):

markdown 复制代码
------------------------------
演示异常情况下的清理:
[ENTER]: 成功打开文件 'test_config.txt',模式为 'r'
[WITH BLOCK]: 尝试读取文件...
[EXIT]: 正在关闭文件 'test_config.txt'...

[外部]: 成功捕获到 ZeroDivisionError。

通过这种方式,我们使用了一个简洁的生成器函数 (open_managed_file),结合 @contextlib.contextmanagertry...finally 结构,优雅且安全地实现了上下文管理。

相关推荐
circuitsosk11 小时前
企业知识库 RAG 从 62% 到 91%:分块策略、混合检索与重排序的调优全记录
python·知识库问答·rag·面试项目·ai工程化·混合检索
烂蜻蜓12 小时前
Flask入门教程(二十六):Session API——用户会话状态管理
后端·python·flask
2603_9651481114 小时前
家居百货蓝海:API挖掘高复购率生活小商品
大数据·服务器·人工智能·python·生活
阿童木写作17 小时前
跨境电商图片翻译工具推荐:批量图片翻译+视频字幕翻译+智能抠图
python·macos·音视频·xcode
cui_ruicheng18 小时前
LangChain 应用开发(十四):Agent 上下文与记忆机制
服务器·人工智能·python·langchain
circuitsosk18 小时前
任务规划器的三种范式对比:ReAct、Plan-and-Execute 与 Tree-of-Thought 在真实业务中的取舍
前端·javascript·python·react.js·llm·ai agent
shehuiyuelaiyuehao18 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
宸津-代码粉碎机19 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
测试199819 小时前
如何用appium搭建Android自动化测试框架?
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
程序员大雄学编程19 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具