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 结构,优雅且安全地实现了上下文管理。

相关推荐
清水白石00818 小时前
Free-Threaded Python 实战指南:机遇、风险与 PoC 验证方案
java·python·算法
飞Link18 小时前
具身智能核心架构之 Python 行为树 (py_trees) 深度剖析与实战
开发语言·人工智能·python·架构
桃气媛媛19 小时前
Pycharm常用快捷键
python·pycharm
Looooking19 小时前
Python 之获取安装包所占用磁盘空间大小
python
WenGyyyL20 小时前
ColBERT论文研读——NLP(IR)里程碑之作
人工智能·python·语言模型·自然语言处理
lxy-up20 小时前
RAG--切片策略
python
ricky_fan20 小时前
(OpenAI)Codex 安装、部署使用方式
python·macos·conda·vim
小王不爱笑13220 小时前
Java 对象拷贝(浅拷贝 / 深拷贝)
java·开发语言·python
Flittly20 小时前
【从零手写 ClaudeCode:learn-claude-code 项目实战笔记】(9)Agent Teams (智能体团队)
python·agent
DevnullCoffe20 小时前
Open Claw × 跨境电商:5个最有价值的 AI Agent 应用场景深度拆解
python·api