2017-02-09 7 views
1

ウェブスクレイピング解析では、永続的に実行する2つのループが必要です.1つはx分ごとに更新されたWebサイトでリストを返し、もう1つはy秒ごとにサイト(古いもの)を分析します。これは私がやろうとしていますが、それは動作しませんどのような、例示コードの構造である:コードは答えと私の研究Pythonで2つの相互依存するwhileループを実行していますか?

from multiprocessing import Process 
import time, random 

from threading import Lock 
from collections import deque 

class MyQueue(object): 
    def __init__(self): 
     self.items = deque() 
     self.lock = Lock() 

    def put(self, item): 
     with self.lock: 
      self.items.append(item) 
# Example pointed at in [this][1] answer 
    def get(self): 
     with self.lock: 
      return self.items.popleft() 

def a(queue): 
    while True: 
     x=[random.randint(0,10), random.randint(0,10), random.randint(0,10)] 
     print 'send', x 
     queue.put(x) 
     time.sleep(10) 


def b(queue): 
    try: 
     while queue: 
      x = queue.get() 
      print 'recieve', x 
      for i in x: 
       print i 
      time.sleep(2) 
    except IndexError: 
     print queue.get() 



if __name__ == '__main__': 
    q = MyQueue() 
    p1 = Process(target=a, args=(q,)) 
    p2 = Process(target=b, args=(q,)) 
    p1.start() 
    p2.start() 
    p1.join() 
    p2.join() 

を組み込むために編集されているので、これが後の私の最初のPythonプロジェクトでありますオンライン入門コースです。私はここで大きな時間を費やしています。私は今、関数が本当に並列に実行されないことを理解しています。なぜなら、aが終了するまでbが始まらないからです(私はthisと答えました。 EDIT:答えに示されたアプローチを使用した後でさえ、queue.get()がIndexErrorをスローするので、両端キューが空であるため、これはまだ当てはまると思います。私は、処理が完了していないと説明することができます。なぜなら、queue.get()を出力すると.put(x)の直後に が出力されるからです。

私は最終的に、このような出力をしたい:私は1つが更新されたリストに、他のループは、分析の基礎として必要とするすべてのx分を返して2つの真の並列ループを持つために

send [3,4,6] 
3 
4 
6 
3 
4 
send [3,8,6,5] #the code above gives always 3 entries, but in my project 
3    #the length varies 
8 
6 
5 
3 
8 
6 
. 
. 

何が必要ですか?プロセスは本当にここに適切なツールですか? そして、どこで私のプログラムの設計に関する良い情報を得ることができますか?

+1

スレッドは間違いなくあなたの問題に最も簡単な答えです!それは恐ろしいかもしれませんが、Pythonでやるのはかなり簡単です。 – Fabich

+0

@Lordofdark私はそのアドバイスを受けてスレッドでも読むでしょう!ありがとう。 – user2822564

答えて

2

少し前にこのようなことをしました。プロセスを使用するのは正しいアプローチだと思いますが、プロセス間でデータを渡したい場合は、おそらくキューを使用する必要があります。

https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes

最初のキューを作成し、両方のプロセスにそれを渡します。 1つはそれに書き込むことができ、もう1つはそこから読み取ることができます。

私が覚えている1つの問題は、何かがプッシュされるまで待ち行列上でブロックされるということです。プロセス1が完了すると、何らかの種類の特別な「終了」メッセージを待ち行列にプッシュする必要があります2は止まることを知っています。

EDIT:簡単な例。これには、プロセスを停止するきれいな方法は含まれません。しかし、2つの新しいプロセスを開始し、一方から他方にデータを渡す方法を示しています。 get()関数bのキューブロックは自動的にaからのデータを待ってから、続行されます。

from multiprocessing import Process, Queue 
import time, random 

def a(queue): 
    while True: 
     x=[random.randint(0,10), random.randint(0,10), random.randint(0,10)] 
     print 'send', x 
     queue.put(x) 
     time.sleep(5) 


def b(queue): 
    x = [] 
    while True: 
     time.sleep(1) 
     try: 
      x = queue.get(False) 
      print 'receive', x 
     except: 
      pass 
     for i in x: 
      print i 


if __name__ == '__main__': 
    q = Queue() 
    p1 = Process(target=a, args=(q,)) 
    p2 = Process(target=b, args=(q,)) 
    p1.start() 
    p2.start() 
    p1.join() 
    p2.join() 
+0

まずは、ありがとうございました。私は待ち行列を読んでいて、それを試してみました。私はあなたの事例を得ることができません。私は 'TypeError: 'キュー'オブジェクトはiterable'ではありません'を取得します。q = Queue.Queue()または何かが不足していませんか?私はその例を見ました。 – user2822564

+0

申し訳ありませんが、少しミスを犯しました。私はこの例を更新し、今回は実際にコードを実行しました。 – trelltron

+0

これは本当に良いです!しかし、私はまだ大きな問題が残っています。あなたのコードは 'i in x'を1回だけ出力します。 'for i in x'の前のwhileループはそれを連続的に出力しますが、新しいqueue.get()を受け付けません。だから私は ''新しいリストを受け取る ''を得るが、 '' print i''は古いリストを表示する。実際のプロジェクトでは、関数1は、関数2が連続的に分析する必要があるURLの変更リストを提供し、リストの新しい入力に対して「受容的」です。これには正しい構成は何ですか? – user2822564

関連する問題