2016-07-29 119 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個線程運行,從隊列中拉出並刮掉一個網頁,或者在這個例子中簡單地打印出被拉出的線。

一旦函數完成,我刪除一個'工作線程',然後一個新的替換它,直到隊列爲空。

在我的現實世界實現某些時候,我將不得不從我的功能scrapes數據並將其寫入.csv文件。但是,現在我只是想了解如何正確實現線程。

我已經看到類似上面的使用'Thread'的例子...並且我還看到了使用繼承類的'線程'示例。我只想知道我應該使用什麼和正確的方式來管理它。

在我這裏很容易,我只是一個試圖理解線程的初學者....是的,我知道它可以變得非常複雜。然而,我認爲這應該是足夠簡單的第一次嘗試...

+0

線程一般來說相當複雜,大多數情況下使用抽象類庫比如多處理(.dummy)或concurrent.futures – janbrohl

回答

2

在Python 2.x multiprocessing.dummy(它使用線程)是一個不錯的選擇,因爲它很容易使用(也可能在Python 3.x中)

如果你發現抓取是CPU限制的,並且你有多個CPU核心,這種方式你可以很簡單地切換到真正的multiprocessing可能獲得一個很大的加速。

(Python中往往不從多個CPU牟利,線程儘可能用,因爲performance optimization的多個進程 - 你必須找出自己究竟是快於你的情況)

隨着mutliprocessing.dummy你可以做

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 

在Python 3.x中,concurrent.futures可能是更好的選擇。

+0

這對我來說似乎更容易乍一看。另外,稍微玩一下,速度會更快。我一直在與腳本的實際抓取部分碰到的一個問題是,我共享變量,我不想分享像我試圖寫入.csv的抓取信息。如果我運行5個線程開始抓取,我會將5個重複項寫入我的csv,儘管刮板正確訪問我想要的頁面。當我鎖定()和釋放()我的線程腳本然後再次線性運行。我怎樣才能防止我的線程寫過別人的數據? –

+0

如果你不想在之後想要放在一起的線程/進程之間共享信息,那麼把它放在你的scrape函數的返回值中 - 如果你不需要寫入函數以外的變量, – janbrohl

+0

我必須說我從示例代碼中學到了很多關於線程和多處理的知識。只是想給你一個感謝。此外,事實證明,多處理對於實施IMO來說要快得多和乾淨得多。只是好奇,如果這是專業開發人員的首選模塊?或者低級線程模塊有什麼好處? –