Python aiohttp:app-dict中的单音实例VS-contextvars VS-globals VS-DI
让我们假设在单个请求中有下一个链:Python aiohttp:app-dict中的单音实例VS-contextvars VS-globals VS-DI,python,dependency-injection,python-asyncio,aiohttp,python-contextvars,Python,Dependency Injection,Python Asyncio,Aiohttp,Python Contextvars,让我们假设在单个请求中有下一个链: some_view->coro_0->coro_1->coro_2->coro_3->coro_4 假设coro_2应该执行redis调用,coro_3-数据库查询和coro_4db和redis调用 根据所有教程等,正确的方法是在函数签名中声明redis_pool和db_engine,例如 异步def coro_2(db_引擎:引擎, redis_池:redis, arg_0:int, arg_1:str, ...) 但是在这种情况下,对于coro_0和co
some_view->coro_0->coro_1->coro_2->coro_3->coro_4
假设coro_2
应该执行redis调用,coro_3
-数据库查询和coro_4
db和redis调用
根据所有教程等,正确的方法是在函数签名中声明redis_pool
和db_engine
,例如
异步def coro_2(db_引擎:引擎,
redis_池:redis,
arg_0:int,
arg_1:str,
...)
但是在这种情况下,对于coro_0
和coro_1
来说,这些变量实际上是不可用的,它们的唯一目的是将它们传递给下一个协同程序。通常,当存在其他arg和更多类似实例时(例如aws客户端、http客户端等),签名会变得太大(?)
我发现的另一个解决方案是contextvars,我声明了一个中间件,它设置了一个db_引擎
,例如:
#声明CV
db_引擎:引擎=ContextVar('db_引擎')
@中间件
异步定义上下文变量中间件(处理程序、请求):
引擎=request.config_dict['db']
db_引擎组(引擎)
...
#在合作项目中:
engine=db_engine.get()
使用engine.acquire()作为连接:
...
这种方法的问题在于,这些变量与“上下文”无关,因为它们是静态的,并且在请求之间不会改变。在我看来,对每个请求进行额外的set
调用是多余的
第三种解决方案-使用依赖项注入模式和库,如下所示:
但对我来说,这似乎是一种非蟒蛇式的方式
第四,使用singleton类并在需要的地方导入它
尽管这四种方法都有效——但我仍然不确定哪一种是“正确的”