从Django运行长时间运行的Python函数

时间:2014-11-23 12:58:46

标签: python django

这是粗略的工作流程:

Request for a job comes in to a particular view -> Job entered in Database -> requestProcessor() launched independent of current process -> Response "Job has been entered" is returned instantly ->

requestProcessor()查看数据库,查看是否有任何待处理的未完成作业,并开始处理它。需要大约3个小时才能完成。

我很长时间以来一直对这个问题感到困惑。我应该使用multiprocessing.Pool的{​​{1}}吗?我对多个流程没有经验,所以我不确定最好的方法是什么。

2 个答案:

答案 0 :(得分:2)

Celery是实现此类精确功能的绝佳工具。您可以使用"任务队列",例如:

tasks.py

from celery import task

@task
def do_job(*args, **kwargs):
    """
    This is the function that does a "job"
    """
    # TODO: Long running task here

views.py

from django.shortcuts import render_to_response

from .tasks import do_job

def view(request):
    """
    This is your view.
    """
    do_job.delay(*args, **kwargs)
    return render_to_response('template.html', {'message': 'Job has been entered'})

调用.delay将注册do_job以供您的一位芹菜工人执行,但不会阻止执行该视图。在工作人员获得自由之前不会执行任务,因此您不应对此方法产生的进程数量有任何问题。

答案 1 :(得分:0)

你应该能够相当容易地做到这一点。这是人们可能使用的Celery(参见Iain Shelvington's answer)。但是,要回答有关多处理模块如何工作的问题,您还可以执行以下操作:

from django.shortcuts import render
from multiprocessing import Process
import time

def do_job(seconds):
    """
    This is the function that will run your three-hour job.
    """
    time.sleep(seconds)                     # just sleep to imitate a long job
    print 'done!'                           # will go to stdout, so you will see this
                                            # most easily in test on local server

def test(request):
    """
    This is your view.
    """
    # In place of this comment, check the database.
    # If job already running, return appropriate template.
    p = Process(target=do_job, args=(15,))  # sleep for 15 seconds
    p.start()                               # but do not join
    message = 'Process started.'
    return render(request, 'test.html',
                  {'message': message})

如果您在本地测试服务器上运行此操作,您将立即进入测试页面,然后在stdout中,您将看到done! 15秒后显示。

如果您要使用此类内容,则还需要考虑在作业完成时是否需要通知用户。此外,您需要考虑是否在第一个工作完成之前阻止进一步的工作请求。我不认为你会希望用户能够随意启动500个进程!您应该检查数据库进程以查看作业是否已在运行。