【问题标题】:Python asyncio contextPython 异步上下文
【发布时间】:2015-08-16 06:27:56
【问题描述】:

在线程中,我们有一个叫做“线程上下文”的东西,我们可以在其中保存一些数据(状态),以便在一个特殊的线程中访问。在 asyncio 中,我需要在当前执行路径中保存一些状态,以便所有后续的协程都可以访问它。解决办法是什么? 注意:我知道每个协程函数都是在 asyncio 中为执行路径实例化的,但由于某种原因,我无法在函数属性中保存状态。 (虽然这个方法os反正不是很好)

【问题讨论】:

标签: python multithreading asynchronous python-asyncio


【解决方案1】:

从 Python 3.7 开始,您可以使用 contextvars.ContextVar

在下面的示例中,我声明了 request_id 并在 some_outer_coroutine 中设置了值,然后在 some_inner_coroutine 中访问它。

import asyncio
import contextvars

# declare context var
request_id = contextvars.ContextVar('Id of request.')


async def some_inner_coroutine():
    # get value
    print('Processed inner coroutine of request: {}'.format(request_id.get()))


async def some_outer_coroutine(req_id):
    # set value
    request_id.set(req_id)

    await some_inner_coroutine()

    # get value
    print('Processed outer coroutine of request: {}'.format(request_id.get()))


async def main():
    tasks = []
    for req_id in range(1, 5):
        tasks.append(asyncio.create_task(some_outer_coroutine(req_id)))

    await asyncio.gather(*tasks)


if __name__ == '__main__':
    asyncio.run(main())

输出:

Processed inner coroutine of request: 1
Processed outer coroutine of request: 1
Processed inner coroutine of request: 2
Processed outer coroutine of request: 2
Processed inner coroutine of request: 3
Processed outer coroutine of request: 3
Processed inner coroutine of request: 4
Processed outer coroutine of request: 4

【讨论】:

【解决方案2】:

还有https://github.com/azazel75/metapensiero.asyncio.tasklocal,但您必须注意,任务通常由库内部创建,也由 asyncio 使用 ensure_future(a_coroutine) 创建,并且没有实际的方法来跟踪这些新任务并初始化它们的本地变量(也许与那些创建它们的任务)。 (一个“黑客”应该设置一个 loop.set_task_factory() 函数来完成这项工作,希望所有代码都使用 loop.create_task() 来创建任务,这并不总是正确的......)

另一个问题是,如果您的某些代码在 Future 回调 Task.current_task() 函数内执行,两个库都使用该函数来选择要服务的正确本地副本副本,则将始终返回 None...

【讨论】:

猜你喜欢
  • 2017-06-05
  • 2018-06-30
  • 1970-01-01
  • 2016-09-22
  • 2014-08-11
  • 2016-01-05
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多