首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ensure_future中的计划任务与上一个任务重叠

ensure_future中的计划任务与上一个任务重叠
EN

Stack Overflow用户
提问于 2018-10-03 23:20:57
回答 1查看 37关注 0票数 1

我需要一个新的处理程序,它使用另一个现有的处理程序来同时处理多个请求:

代码语言:javascript
复制
async def process_multiple_queries(request):
    init_request = request.clone()
    body = await request.json()

    for query in body["queries"]:

        @asyncio.coroutine
        def fake_json(self):
            return query

        # Replace request body on new fake json
        R = init_request.clone()
        R.json = fake_json.__get__(R, Request)

        # Process request in the background task
        asyncio.ensure_future(process_query(R))

async def process_query(request):
    body = await request.json()
    # ... Process body ...
    return web.json_response({"result": "OK"})

但是,所有定时任务的结果都等于最后一个任务的结果,即process_query中传入的所有请求的body只与最后一个请求的body相同。

但是如果我在asyncio.ensure_future(process_query(R))之后添加asyncio.sleep(5),所有的任务都会被正确地处理并产生不同的结果。

如何修复它?

EN

回答 1

Stack Overflow用户

发布于 2018-10-04 00:58:36

这是well-known Python的陷阱,闭包通过名称而不是值来捕获变量。因此,fake_json协程的所有实例都引用相同的query 变量,因此所有实例最终都引用其已知值。

要解决此问题,您需要更改定义:

代码语言:javascript
复制
        @asyncio.coroutine
        def fake_json(self):
            return query

到捕捉query价值的公式,例如:

代码语言:javascript
复制
        @asyncio.coroutine
        def fake_json(self, query=query):
            return query

await asyncio.sleep(5)很有帮助,因为它允许process_queryquery的值发生变化之前运行到完成。使用await process_query(R)也会得到同样的效果。

与问题无关的两点:

@asyncio.coroutine装饰器

  • deprecated,没有理由在新代码中使用它(除非您特别想与3.5Python3.5之前的版本兼容)。相反,简单地使用async def.
  • You定义fake_json不需要调用__get__来将self绑定到甚至不使用它的fake_json。您可以简单地分配R.json = fake_json.

来定义一个不需要selffake_json

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52630461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档