2012-08-17 83 views
1

我有python/django代码托管在dotcloud和redhat openshift上。为了处理不同的用户,我使用令牌并将其保存在字典中。但是,当我从字典中获得值时,它有时会引发错误(键值错误)。django/python:从字典中获取值时出错

import threading 

thread_queue = {} 

def download(request): 
    dl_val = request.POST["input1"] 
    client_token = str(request.POST["pagecookie"]) 
     # save client token as keys and thread object as value in dictionary 
    thread_queue[client_token] = DownloadThread(dl_val,client_token) 
    thread_queue[client_token].start() 
    return render_to_response("progress.html", 
       { "dl_val" : dl_val, "token" :  client_token }) 

下面的代码以1秒的间隔通过javascript xmlhttprequest执行到服务器。 它将检查另一个线程中的变量并将值返回给用户页面。

def downloadProgress(request, token): 
     # sometimes i use this for check the content of dict 
    #resp = HttpResponse("thread_queue = "+str(thread_queue)) 
    #return resp 
    prog, total = thread_queue[str(token)].getValue() # problematic line ! 
    if prog == 0: 
       # prevent division by zero 
     return HttpResponse("0") 
    percent = float(prog)/float(total) 
    percent = round(percent*100, 2) 
    if percent >= 100: 
     try: 
      f_name = thread_queue[token].getFileName()[1] 
     except: 
      downloadProgress(request,token) 
     resp = HttpResponse('<a href="http://'+request.META['HTTP_HOST']+ 
          '/dl/'+token+'/">'+f_name+'</a><br />') 
     return resp 
    else: 
     return HttpResponse(str(percent)) 

测试几天后,它有时会返回:

thread_queue = {} 

有时候成功:

thread_queue = {'wFVdMDF9a2qSQCAXi7za': , 'EVukb7QdNdDgCf2ZtVSw': , 'C7pkqYRvRadTfEce5j2b': , '2xPFhR6wm9bs9BEQNfdd': } 

我,当我通过管理本地运行的Django从来没有得到这样的结果。 py runserver,并通过谷歌浏览器访问它,但是当我将它上传到dotcloud或openshift时,它总是会出现上述问题。 我的问题:

  • 我该如何解决这个问题?
  • dotcloud和openshift是否限制他们的python cpu使用?
  • 或者是python字典里面的问题?

谢谢。

回答

3

dotCloud默认有4个工作进程用于python服务。当你在本地运行开发服务器时,你只运行一个进程。就像@martijn所说,你的问题与你的词典不会在这些过程之间共享的事实有关。

要解决此问题,您可以使用类似redis或memcached的内容来存储此信息。如果您需要更长期的存储解决方案,那么使用数据库可能更适合。

dotCloud不限制CPU使用率,CPU在同一台主机上共享,并允许突发,但最终每个人都有相同数量的CPU。

查看你的代码,你应该检查以确保在你访问dict之前有一个值,或者至少用一个除了block之外的代码包围代码来处理数据不是的情况那里。

str_token = str(token) 
if str_token in thread_queue: 
    prog, total = thread_queue[str_token].getValue() # problematic line ! 
else: 
    # value isn't there, do something else 
+0

谢谢,我会努力的Redis – Alvin 2012-08-17 17:57:09

+0

在我的代码,即时存储线程对象字典。我可以拥有与redis相同的内容来存储我的线程对象吗? – Alvin 2012-08-17 18:17:19

+0

@alvin,如果你的线程对象可以被腌制,你可以腌制它,并将它存储在redis中,就像你将它存储在本地字典中一样,你的密钥将是你今天使用的相同标记,并且值将是你的pickled目的。当你想要的时候,你可以把它拉出来,取出它,然后你就可以像以前一样使用它。 – 2012-08-17 21:02:39

2

推测dotcloud和openshift运行你的代码的多个进程;字典不会在这些过程之间共享。

请注意,这也意味着额外的过程将无法访问您的额外胎面。

改为使用这种信息的外部数据库。对于像这些长时间运行的异步作业,您还需要在单独的工作进程中运行它们。例如,请看Celery为异步作业处理提供一体化解决方案。

+0

THX,答案,它如此有用,我会尝试芹菜 – Alvin 2012-08-17 17:56:02