python – 报告产生了长期运行的Celery任务的结果 - 代码日志

python – 报告产生了长期运行的Celery任务的结果

问题

我将一个长时间运行的任务划分为逻辑子任务,所以我可以在完成后报告每个子任务的结果。然而,我正在尝试报告一个任务的结果,这个任务将无法完成(而是产生价值),而我正在努力地利用我现有的解决方案。

背景

我正在为一些我编写的Python程序构建一个Web界面。用户可以通过网页表单提交作业,然后查看工作进度。

假设我有两个功能,每个功能通过单独的窗体访问:

> med_func:执行约1分钟,结果被传递给render(),它产生额外的数据。
> long_func:返回一个生成器。每个产量大约需要30分钟,并应向用户报告。有这么多的收益,我们可以将这个迭代器视为无限(仅在revoked时终止)。

代码,当前实现

使用med_func,我报告结果如下:

在表单提交时,我将AsyncResult保存到Django session

    task_result = med_func.apply_async([form], link=render.s())
    request.session["task_result"] = task_result

结果页面的Django视图访问此AsyncResult。任务完成后,结果将保存到一个上下文传递给Django模板的对象中。

def results(request):
    """ Serve (possibly incomplete) results of a session's latest run. """
    session = request.session

    try:  # Load most recent task
        task_result = session["task_result"]
    except KeyError:  # Already cleared, or doesn't exist
        if "results" not in session:
            session["status"] = "No job submitted"
    else:  # Extract data from Asynchronous Tasks
        session["status"] = task_result.status
        if task_result.ready():
            session["results"] = task_result.get()
            render_task = task_result.children[0]

            # Decorate with rendering results
            session["render_status"] = render_task.status
            if render_task.ready():
                session["results"].render_output = render_task.get()
                del(request.session["task_result"])  # Don't need any more

    return render_to_response('results.html', request.session)

该解决方案仅在函数实际终止时才起作用。我无法将long_func的逻辑子任务链接在一起,因为有一个未知的收益数量(long_func循环的每个迭代可能不会产生结果)。

有没有什么明智的方法可以从极长时间运行的Celery任务中访问生成的对象,以便在生成器耗尽之前可以显示它们?

为了让Celery知道任务的当前状态,它会设置一些元数据,无论你拥有什么后果。你可以捎带来存储其他种类的元数据。

def yielder():
    for i in range(2**100):
        yield i

@task
def report_progress():
    for progress in yielder():
        # set current progress on the task
        report_progress.backend.mark_as_started(
            report_progress.request.id,
            progress=progress)

def view_function(request):
    task_id = request.session['task_id']
    task = AsyncResult(task_id)
    progress = task.info['progress']
    # do something with your current progress

我不会在那里扔大量的数据,但它可以很好地跟踪长时间运行的任务的进度。

http://stackoverflow.com/questions/17052291/reporting-yielded-results-of-long-running-celery-task

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:python – 报告产生了长期运行的Celery任务的结果