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

相关推荐
隔壁大炮几秒前
MNE-Python 第1天学习笔记:环境搭建与数据初探
python·eeg·bci·mne·脑电数据处理
晚烛1 分钟前
CANN 模型热更新:不停机模型切换与无缝更新实战指南
开发语言·python
ZPC82101 分钟前
单物体最优抓取轨迹生成
python·opencv·计算机视觉
若兰幽竹18 分钟前
【大模型应用】抖音爆款视频深度分析系统:流水线式AI逆向拆解流量密码,精准预测播放量!
人工智能·python·音视频·抖音爆款分析
喜爱波波奶茶21 分钟前
doxygen python配置
python
这是空气22 分钟前
Python 入门教程3
python
心中有国也有家22 分钟前
pytorch-adapter:让 PyTorch 模型“无缝”跑在昇腾 NPU 上
人工智能·pytorch·笔记·python·学习
import_random25 分钟前
[python]numpy模块(详解)
python
SilentSamsara42 分钟前
泛型与 Protocol:结构化子类型的地道写法
开发语言·python·青少年编程
独隅1 小时前
PyCharm 接入 Codex 的全面指南
ide·python·pycharm