2014-11-23 53 views
1

一个长期运行的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.Poolapply_async?我没有多个流程的经验,所以我不确定最好的方法是什么。

回答

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个进程!你应该检查你的数据库进程,看看作业是否已经在运行。

+0

这和'pool = Pool(processes = 1)有什么区别?结果= pool.apply_async(myfunction)'方法?考虑到我正在调用一个Python函数本身,这似乎更方便一些。 – user1265125 2014-11-23 13:45:18

+0

@ user1265125“池”用于工作进程池。我相信你在这里只需要一个过程。那是对的吗?你的描述表明这可能是一种行政型工作。我的答案中的方法还调用了一个python函数(我已经任意命名为'do_job')。 – 2014-11-23 13:47:49

+0

如果经常调用视图,这将导致发生无法控制的进程增长。 – 2014-11-23 13:50:00

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执行但不会阻止视图的执行。一个任务不会被执行,直到工人变得自由,所以你不应该对这种方法产生的进程数量有任何问题。