J'Blog

17 课 · 进阶

语义检索

基于 Chroma 向量库,与 Workspace 知识库分离。用自然语言描述你想查的内容。 非管理员每人每天可检索 5 次(消耗站点 AI 配额)。

上下文管理器

原文:上下文管理器

一句话

提供创建和管理上下文管理器的工具,确保资源正确释放。

什么时候翻这页

  1. 需要创建自定义工具函数供Agent调用时
  2. 处理异步资源管理(如数据库连接、API调用)时
  3. 需要结构化输出或错误处理时
  4. 组合多个工具调用并确保正确清理时

核心概念

  1. 上下文管理器:实现了__enter____exit__方法的对象,用于资源的获取和释放
  2. 异步上下文管理器:实现了__aenter____aexit__方法的对象,用于异步资源的获取和释放
  3. 装饰器模式:通过@contextmanager@asynccontextmanager将生成器函数转换为上下文管理器
  4. 资源管理:确保资源在使用后正确释放,即使在异常情况下
  5. 上下文组合:使用ExitStackAsyncExitStack组合多个上下文管理器

怎么做

  1. 创建简单的上下文管理器:
from contextlib import contextmanager

@contextmanager
def managed_resource(*args, **kwds):
    resource = acquire_resource(*args, **kwds)
    try:
        yield resource
    finally:
        release_resource(resource)
  1. 创建异步上下文管理器:
from contextlib import asynccontextmanager

@asynccontextmanager
async def get_connection():
    conn = await acquire_db_connection()
    try:
        yield conn
    finally:
        await release_db_connection(conn)
  1. 使用上下文管理器装饰器:
@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()
  1. 组合多个上下文管理器:
with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # 所有文件将在退出时自动关闭

命令 / API 速查

函数/类描述
@contextmanager将生成器函数转换为上下文管理器
@asynccontextmanager将异步生成器函数转换为异步上下文管理器
closing(thing)创建在退出时调用close()方法的上下文管理器
aclosing(thing)创建在退出时调用aclose()方法的异步上下文管理器
suppress(*exceptions)创建抑制指定异常的上下文管理器
redirect_stdout(new_target)重定向标准输出的上下文管理器
redirect_stderr(new_target)重定向标准错误的上下文管理器
ContextDecorator使上下文管理器可用作装饰器的基类
AsyncContextDecorator使异步上下文管理器可用作装饰器的基类
ExitStack组合多个上下文管理器和清理操作的上下文管理器
AsyncExitStack组合多个异步上下文管理器和清理操作的异步上下文管理器
nullcontext(enter_result=None)不执行任何操作的上下文管理器,用作可选上下文管理器的占位符

与 Agent 开发的联系

  1. 工具封装:使用@contextmanager@asynccontextmanager创建结构化的工具函数,确保资源正确管理
  2. 异步调用:通过异步上下文管理器处理数据库连接、API调用等异步资源,适合Agent的异步执行模型
  3. 错误处理:使用suppressExitStack构建健壮的错误处理机制,确保Agent在工具调用失败时能优雅恢复
  4. 资源管理:通过上下文管理器确保文件、网络连接等资源在使用后正确释放,避免资源泄漏

初学者易错点

  1. 上下文管理器只能yield一次,多次使用会导致"generator didn't yield"错误
  2. 异步上下文管理器必须使用async with语句,不能与普通with混用
  3. 忽略异常处理:在try块中yield后,必须在finally块中确保资源释放
  4. 可重入与线程安全混淆:可重入上下文管理器可以在嵌套的with语句中使用,但不一定是线程安全的
  5. 上下文管理器装饰器无法访问__enter__的返回值,需要显式使用with语句获取

相关词条

  • library-contextmanager - Python上下文管理器协议详解
  • library-asyncio - 异步编程基础
  • library-threading - 线程与并发
  • library-exceptions - 异常处理机制
  • library-functools - 函数式工具
  • library-types - 类型系统与注解

官方原文:https://docs.python.org/zh-cn/3/library/contextlib.html