2016-07-29 16 views
2

私はスレッド化されたスクリプトで初めての試みをしようとしています。最終的には、私が以前に作ったオリジナルの線形スクレイピングスクリプトより少し速く動くことを望むウェブスクレーパーになるだろう。Pythonスレッド/スレッドの実装

いくつかのサンプルコードで読んだり演奏したりしています。インプリメンテーションが正しい限り、正しいと思われるものはまだわかりません。

from Queue import Queue 
import threading 

def scrape(queue): 
    global workers 
    print worker.getName() 
    print queue.get() 
    queue.task_done() 
    workers -= 1 

queue = Queue(maxsize=0) 
threads = 10 
workers = 0 


with open('test.txt') as in_file:  
    for line in in_file: 
     queue.put(line) 

while not (queue.empty()): 
    if (threads != workers): 
     worker = threading.Thread(target=scrape, args=(queue,)) 
     worker.setDaemon(True) 
     worker.start() 
     workers += 1 

アイデアは私があるtest.txtファイル内のURLのリストを持っているということです。

は現在、私は私が演奏されている次のコードを持っています。私はファイルを開き、すべてのURLをキューに入れます。そこから、キューからプルして10個のスレッドを実行し、Webページをスクラップするか、この例では単にプルされた行をプリントアウトします。

機能が完了すると、「ワーカースレッド」が削除され、キューが空になるまで新しいワーカースレッドが置き換えられます。

私の実際の実装では、ある時点で私の関数スクレイプからデータを取り出して.csvファイルに書き込む必要があります。しかし、今は、スレッドを正しく実装する方法を理解しようとしています。

私は、上記の「Thread」を使用した同様の例を見てきました。また、継承したクラスを利用する「スレッド」の例も見てきました。私は何を使うべきか、それを管理する正しい方法を知りたいだけです。

私はここで簡単に移動できます。初心者はスレッドを理解しようとしています....そして、はい、私はそれが非常に複雑になる可能性があることを知っています。しかし、私はこれが最初の試行のために十分に簡単であるべきだと思います...

+0

一般的なスレッディングはかなり複雑で、ほとんどの場合、マルチプロセッシング(.dummy)やコンカレントなどの抽象ライブラリを使用する方が簡単です – janbrohl

答えて

2

On Python 2.x multiprocessing.dummy(これはスレッドを使用します)は使いやすい(Python 3.xでも可能です)

CPUが制限されていて、複数のCPUコアを持っていることが判明した場合は、実際にmultiprocessingに切り替えることで大きなスピードアップを得ることができます。

(Pythonがしばしばperformance optimizationの複数のプロセスと同じくらいのスレッドで複数のCPUから利益をしない - あなたはあなたのケースで速くなるものを自分自身を見つけるために持っている)あなたができるmutliprocessing.dummyで

をPythonの3.xの上

from multiprocessing.dummy import Pool 
# from multiprocessing import Pool # if you want to use more cpus 

def scrape(url): 
    data = {"sorted": sorted(url)} # normally you would do something more interesting 
    return (url, data) 

urls=[] 
threads = 10 

if __name__=="__main__": 
    with open('test.txt') as in_file:  
     urls.extend(in_file) # lines 

    p=Pool(threads) 
    results=list(p.imap_unordered(scrape,urls)) 
    p.close() 
    print results # normally you would process your results here 

concurrent.futuresは、より良い選択かもしれません。

+0

一見するとはるかに簡単です。さらに、それを少しでも遊んだ後は、より速くなります。私が実際にスクリプトの一部を掻き集めている1つの問題は、私が.csvに書き込もうとしているスクレイプされた情報のように、共有したくない変数を共有していることです。スクラップを開始するために5つのスレッドを実行すると、スクレイパーが適切なページに正しくアクセスしているにもかかわらず、5つの複製がCSVに書き込まれます。私のスレッドをLock()およびRelease()すると、スクリプトは再び直線的に実行されます。私のスレッドが互いのデータを上書きするのを防ぐにはどうしたらいいですか? –

+0

後でまとめたいスレッド/プロセス間で情報を共有したくない場合は、スクレイプ関数の戻り値にその値を入れてください - あなたの関数外の変数に書き込まないでください – janbrohl

+0

私は言う必要がありますあなたのサンプルコードからスレッドとマルチプロセッシングについて多くのことを学びました。ちょうど感謝したいと思います。また、明らかになったように、マルチプロセッシングは、IMOを実装するためにはるかに高速でクリーンでした。それがプロの開発者のために選んだモジュールであるかどうか不思議です。または、低レベルのスレッドモジュールに利点がありますか? –