如何让Graphene所有解析器在上下文管理器中执行?
如何让Graphene所有解析器在Aiohttp Client Session上下文管理器中执行?
当然有可行的方案!结合aiohttp推荐的单应用复用一个Client Session的原则,以及Graphene对异步执行器的支持,我们可以通过上下文注入的方式,让所有解析器都共享同一个Client Session的上下文环境。下面是具体的实现思路和代码示例:
核心思路
Graphene的异步解析器可以访问GraphQL的执行上下文(info.context),我们可以在请求的入口处(比如aiohttp-graphql的路由配置里),把预先初始化好的全局Client Session注入到这个上下文中,这样所有解析器都能从上下文里获取到同一个Session,自然就运行在它的上下文管理器作用域内了。
具体实现步骤
1. 全局初始化Client Session
按照aiohttp的最佳实践,我们在应用启动时创建一个全局的Client Session,整个应用生命周期内复用它,避免频繁创建销毁连接:
from aiohttp import web from aiohttp_graphql import GraphQLView import graphene # 先定义你的Graphene Query类型 class Query(graphene.ObjectType): async def resolve_fetch_external_data(self, info): # 从上下文里拿到复用的Session session = info.context["client_session"] # 直接用这个Session发起请求,不用每次都创建新的上下文管理器 async with session.get("https://example.com/api/data") as resp: return await resp.json() # 构建Schema schema = graphene.Schema(query=Query) async def create_app(): app = web.Application() # 全局初始化Client Session,整个应用复用 app["client_session"] = web.ClientSession() # 定义上下文工厂:把全局Session注入到GraphQL执行上下文 async def context_factory(request): return {"client_session": request.app["client_session"]} # 添加GraphQL路由,启用异步执行器 app.add_routes([ web.post("/graphql", GraphQLView.as_view( schema=schema, context_factory=context_factory, enable_async=True # 必须开启异步执行,才能运行async解析器 )) ]) # 应用关闭时,记得关闭全局Session,避免资源泄漏 async def on_app_shutdown(app): await app["client_session"].close() app.on_shutdown.append(on_app_shutdown) return app if __name__ == "__main__": web.run_app(create_app())
2. 在解析器中使用上下文里的Session
所有异步解析器都可以通过info.context["client_session"]获取到同一个全局Session,所有基于这个Session的HTTP请求,都运行在它的上下文管理器作用域内,完美符合aiohttp的复用建议。
关键注意事项
- 必须启用异步执行:确保Graphene的GraphQLView开启了
enable_async=True,同时解析器要用async def定义,否则无法处理异步操作。 - 资源清理不能忘:一定要在应用关闭钩子中关闭全局Session,否则会有连接泄漏的风险。
- Session复用策略:如果你的应用有特殊需求(比如每个请求需要独立Session),也可以在
context_factory里为每个请求创建新的Session,但这不符合aiohttp的最佳实践,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者stepuncius
相关产品推荐
相关产品推荐

