【问题标题】:Simple threading in DjangoDjango中的简单线程
【发布时间】:2014-11-17 20:04:34
【问题描述】:

我需要在 Django 中实现线程。我需要三个简单的 API:

  1. /work?process=data1&jobid=1&jobtype=nonasync
  2. /状态
  3. /kill?jobid=1

API 说明如下:

  1. work api 将采用process 并生成一个处理它的线程。现在,我们可以假设它是一个简单的sleep(10) 方法。它将线程命名为jobid-1。该线程应该可以通过此名称检索。如果 jobid 已存在,则无法创建新线程。 jobtype 可以是 async,即 api 调用将在生成线程后立即返回 http status code 200。也可以是nonasync,这样api就等待服务器完成线程并返回结果。
  2. status api 应该只显示每个正在运行的进程的状态。
  3. kill api 应该基于jobid 杀死一个进程。 status api 不应再显示此作业。

这是我的 Django 代码:

processList = []


class Processes(threading.Thread):
""" The work api can instantiate a process object and monitor it completion"""

    threadBeginTime = time.time()

    def __init__(self, timeout, threadName, jobType):
        threading.Thread.__init__(self)
        self.totalWaitTime = timeout
        self.threadName = threadName
        self.jobType = jobtype

    def beginThread(self):
        self.thread = threading.Thread(target=self.execution,
            name = self.threadName)
        self.thread.start()

    def execution(self):
        time.sleep(self.totalWaitTime)

    def calculatePercentDone(self):
        """Gets the current percent done for the thread."""
        temp = time.time()
        secondsDone = float(temp - self.threadBeginTime)
        percentDone = float((secondsDone) * 100 / self.totalWaitTime)
        return (secondsDone, percentDone)

    def killThread(self):
        pass
        # time.sleep(self.totalWaitTime)

def work(request):
    """ Django process initiation view """
    data = {}
    timeout = int(request.REQUEST.get('process'))
    jobid = int(request.REQUEST.get('jobid'))
    jobtype = int(request.REQUEST.get('jobtype'))
    myProcess = Processes(timeout, jobid, jobtype)
    myProcess.beginThread()
    processList.append(myProcess)
    return render_to_response('work.html',{'data':data}, RequestContext(request))


def status(request):
    """ Django process status view """
    data = {}
    for p in processList:
        print p.threadName, p.calculatePercentDone()

    return render_to_response('server-status.html',{'data':data}, RequestContext(request))


def kill(request):
    """ Django process kill view """
    data = {}
    jobid = int(request.REQUEST.get('jobid'))
    # find jobid in processList and kill it
    return render_to_response('server-status.html',{'data':data}, RequestContext(request))

上面的代码有几个实现问题。线程生成没有以正确的方式完成。我无法在status 函数中检索进程状态。此外,由于我无法从其作业 ID 中获取线程,因此仍然实现了 kill 功能。需要帮助重构。

更新:我做这个例子是为了学习,而不是为了编写生产代码。因此不会支持任何现成的队列库。这里的目标是了解多线程如何与 Web 框架结合使用,以及需要处理哪些边缘情况。

【问题讨论】:

  • 试图自己实现这一点是灾难的根源。使用久经考验的现有解决方案 Celery。
  • @DanielRoseman 我不是在这里寻找生产代码。更像是关于线程和 Django 的概念学习。需要使用裸线程库来完成工作。

标签: python django multithreading


【解决方案1】:

正如上面提到的@Daniel Roseman —— 在 Django 请求/响应周期内进行线程处理是一个非常糟糕的主意,原因有很多。

您实际上在这里寻找的是任务队列。

有一些库可以让这种事情变得相当简单——我将按照易用性的顺序在下面列出它们(最简单的列在最前面):

只要我的两分钱。

【讨论】:

  • rdegges 正如我在上面的评论中提到的,了解线程如何工作的内在缠绕对我来说很重要。当然,您的建议非常适合编写生产就绪代码并跳过重新发明轮子。但这里的目标是学习。
猜你喜欢
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
  • 2022-01-10
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
相关资源
最近更新 更多