【问题标题】:how to replace thread_locals logic on async code?如何替换异步代码上的 thread_locals 逻辑?
【发布时间】:2022-11-29 01:00:11
【问题描述】:
在一个 Django 项目中,我有很多依赖于 thread_locals 的代码:使用相关 ID 的中间件、依赖于这些中间件的其他逻辑、有关请求的缓存信息等等。
最近我开始将同步代码与异步混合,并且由于我有一个线程服务于异步部分,所以我不能再使用 thread_locals 了。因为我使用了很多 sync_to_async 和 async_to_sync 适配器,所以我不能使用上下文变量,因为在同一个请求中会执行不同的协程。
我有什么替代方法来管理每个请求所特有的短期信息?我考虑过将所有内容存储在 redis 上作为缓存,但同样,如何显示我在执行过程中的几个点上从每个请求生成/检索密钥?
【问题讨论】:
标签:
django
multithreading
python-asyncio
coroutine
django-middleware
【解决方案1】:
Python 有 contextvars lib 模块来为异步代码提供线程本地的一些功能。 https://docs.python.org/3/library/contextvars.html-
然而,contextvars 的 API 并不相同——相反,每个 context_var 只能承载一个值,并且必须通过方法调用而不是 = 运算符来设置和重置。
我在 contextvars 正式发布之前创建了一个项目,它试图提供一个更像 threadlocals 的“上下文” - 如果你想尝试它,它目前必须直接从 git 进行 pip 安装 - 主要问题是
我没有现实世界的项目需要它,这让我付出了额外的努力来完善它以便在 Pypi 上发布 -
尽管如此,它可以完美地处理我能想到的所有测试场景——该项目位于https://github.com/jsbueno/extracontext,可以通过pip install git+https://github.com/jsbueno/extracontext.git@0.2b3进行pip安装。