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

相关推荐
A__tao4 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
研究点啥好呢4 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
迷藏4944 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
明日清晨5 小时前
python扫码登录dy
开发语言·python
bazhange5 小时前
python如何像matlab一样使用向量化替代for循环
开发语言·python·matlab
人工干智能5 小时前
科普:python中你写的模块找不到了——`ModuleNotFoundError`
服务器·python
unicrom_深圳市由你创科技6 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
小敬爱吃饭6 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
宸津-代码粉碎机6 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
知行合一。。。6 小时前
Python--04--数据容器(集合)
python