2012-08-17 80 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