2017-06-27 13 views
0

ユーザーはhttp://example.com/url/を訪問し、views.pyからpage_parserを呼び出します。 page_parserclass Fooのインスタンスをscript.pyから作成します。 http://example.com/url/が訪問されるたびに、メモリ使用量が増えています。ガベージコレクタはインスタンス化されたclass Fooを収集しないと思います。それはどんなアイデアなのですか?ここで Django、Queue、Thread - メモリを解放しないでください

はコードです:

views.py:

from django.http import HttpResponse 
from script import Foo 
from script import urls 

# When user visits http://example.com/url/ I run `page_parser` 
def page_parser(request): 
    Foo(urls) 
    return HttpResponse("alldone") 

script.py:

import requests 

from queue import Queue 
from threading import Thread 


class Newthread(Thread): 
    def __init__(self, queue, result): 
     Thread.__init__(self) 
     self.queue = queue 
     self.result = result 

    def run(self): 
     while True: 
      url = self.queue.get() 
      data = requests.get(url) # Download image at url 
      self.result.append(data) 
      self.queue.task_done() 


class Foo: 
    def __init__(self, urls): 
     self.result = list() 
     self.queue = Queue() 
     self.startthreads() 
     for url in urls: 
      self.queue.put(url) 
     self.queue.join() 

    def startthreads(self): 
     for x in range(3): 
      worker = Newthread(queue=self.queue, result=self.result) 
      worker.daemon = True 
      worker.start() 


urls = [ 
    "https://static.pexels.com/photos/106399/pexels-photo-106399.jpeg", 
    "https://static.pexels.com/photos/164516/pexels-photo-164516.jpeg", 
    "https://static.pexels.com/photos/206172/pexels-photo-206172.jpeg", 
    "https://static.pexels.com/photos/32870/pexels-photo.jpg", 
    "https://static.pexels.com/photos/106399/pexels-photo-106399.jpeg", 
    "https://static.pexels.com/photos/164516/pexels-photo-164516.jpeg", 
    "https://static.pexels.com/photos/206172/pexels-photo-206172.jpeg", 
    "https://static.pexels.com/photos/32870/pexels-photo.jpg", 
    "https://static.pexels.com/photos/32870/pexels-photo.jpg", 
    "https://static.pexels.com/photos/106399/pexels-photo-106399.jpeg", 
    "https://static.pexels.com/photos/164516/pexels-photo-164516.jpeg", 
    "https://static.pexels.com/photos/206172/pexels-photo-206172.jpeg", 
    "https://static.pexels.com/photos/32870/pexels-photo.jpg"] 
+1

具体的な内容がわからないと、終了条件やキューが設定されていないエンドレスループのデーモンスレッドが表示されます。だから、まあまあ期待どおりに動作します。 – Melvyn

+0

@Melvyn Djangoのビューではない 'class Foo'のインスタンスを作成すると、スクリプトは終了します(すべてのURLをダウンロードして、何とか処理が終了します)。私は正しい方向に向けることができます - 私はDjangoのビューでスクリプトを使用すると、すべてのキューとスレッドを終了したいと思います。 –

+0

@Melvynあなたのコメントから私はそれを推測します: a)特定のアイテムがキューから出るときにwhileループで 'break'を追加するb)特定のアイテムをキューに入れる –

答えて

0

あり、いくつかの可動部品が関与ですが、私は考えて起こることは以下の通りです:

  1. WSGIプロセスはkiではありませんそれぞれの要求の後にはまります。
  2. 3つの新しいスレッドを作成しますが、たとえばキューが空の場合など、再びメインスレッドに参加させないでください。
  3. Foo.queueへの参照カウントがゼロになることはありませんので、(スレッドがまだ新しいキュー項目を待って生きているように)、それはゴミが

を収集することができないので、新しいスレッド、新しいはFooクラスのどれを作成しておきますそれらは解放することができます。

私はqueue.Queueのエキスパートではありませんが、WSGIプロセスのスレッド数が3つの要求(たとえば、top(1)を使用)で上がっているのを見ることができれば私の理論を検証できます。

副作用として、これはクラス設計の副作用です。あなたは__init__ですべてを行いますが、実際にはクラス属性のみを割り当てる必要があります。

関連する問題