如何从视图中的异步事件循环中获取任务?

时间:2019-06-30 09:49:57

标签: python python-asyncio aiohttp

在使用aiohttp编写的Web应用程序中,我有2个端点。首先是启动异步任务,这是无限循环。第二个旨在取消某些任务。由于异步任务没有任何ID概念,我有点困惑。 是否可以在数据库中保存任务的某些标识符? 是这样做的正确方法,还是lib已经为此类问题提供了解决方案?

aiohttp_app / views.py

from aiohttp import web

import asyncio
import json


async def coro(frequency):
    while True:
         print('Infinite loop iteration')
         await asyncio.sleep(frequency)


def start_task(request):
    event_loop = asyncio.get_event_loop()
    task = event_loop.create_task(coro())
    # save some identifier of the task in the database to find it later
    response = dict()
    return web.json_response(json.dumps(response))


def stop_task(request):
     task = None  # here i must get a certain task outta event loop
     task.cancel()
     response = dict()
     return web.json_response(json.dumps(response))

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您可以生成简单的单调递增的数字ID,并具有将ID映射到任务实例的全局字典。协程完成后,映射将被删除。例如(未试用):

import asyncio, itertools

_next_id = itertools.count().__next__
_tasks = {}

def make_task(corofn, *coroargs):
    task_id = _next_id()
    async def wrapped_coro():
        try:
            return await corofn(*coroargs)
        finally:
            del _tasks[task_id]
    task = asyncio.create_task(wrapped_coro())
    _tasks[task_id] = task
    return task_id, task

def get_task(task_id):
    return _tasks[task_id]

然后您可以在start_taskstop_task中使用它:

def start_task(request):
    task_id, _ = make_task(coro)
    response = {'task_id': task_id}
    return web.json_response(json.dumps(response))

def stop_task(request):
     task_id = json.loads(await request.text())['task_id']
     task = get_task(task_id)
     task.cancel()
     response = {}
     return web.json_response(json.dumps(response))