2015-08-21 90 views
1

在你的下方看到我的抓取工具的藍圖。我想我可以用多線程加速它,但我不能。很多時候,當我加載一個網頁時,網絡服務器速度很慢,然後爬上另一個多線程加載速度更快的網頁會很好。但它不會更快。爲什麼?爲什麼我不能加快python中的多線程爬行?

def start_it(): 
    while(True): 
     get_urls() 

def get_urls(): 
    response = urllib2.urlopen(url) 
    page_source = str(response.read()) 

pool = ThreadPool(10) 

pool.map(start_it()) 

好吧我測試過,如果線程並行運行,它們不是:/我在做什麼錯了?

def start_it(): 

    x = random.random() 
    while(True): 
     get_urls(x) 

def get_urls(x): 
    print(x) 

pool = ThreadPool(10) 

pool.map(start_it()) 

我知道這是因爲輸出始終是相同的:

0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
+1

你確定你的線程實際上是同時運行嗎?把一些日誌記錄放進去。你知道GIL及其對線程代碼的影響嗎?微型加工可能會更好。 – scytale

+0

多處理有什麼區別? –

+0

請詳細閱讀我以前的評論 – scytale

回答

-1

我認爲這種方式可以忠實地平行延伸。我經歷了爬行的顯着加速。真棒;)

import multiprocessing 
import random 

def worker(): 
    """worker function""" 

    x = random.random()*10 
    x = round(x) 
    while(True): 
     print(x , ' Worker') 

if __name__ == '__main__': 
    jobs = [] 
    for i in range(5): 
     p = multiprocessing.Process(target=worker) 
     jobs.append(p) 
     p.start() 
+0

讓我們說它是作爲多個流程運行的,真正平行的可能不是。 – lxx

+0

它的確如此。從文檔:'過程對象表示在單獨的進程中運行的活動'。你可以通過在每個worker中打印os.getpid()來驗證,你會看到它。 – csl

+0

不要忘記'加入'你的過程。 – csl

2

,你需要在你運行start_it()的時刻提供pool.map()可迭代

基本上運行您的來電相繼。我不知道你用的是什麼實現的ThreadPool但你可能需要做一些事情,如:

pool.map(get_urls, list_of_urls) 
+0

我沒有url列表,因爲每個get_urls()進程都需要一個url數據庫的條目 –

+1

很好地適應了我讓我們看看 – scytale

0

不離題,但異步IO也是你的問題一個很好的候選人。您可以使用一個名爲asyncio的驚人庫,它最近已被添加到python 3.4中。對於舊版本,您可以使用trolliusTwisted

0

如果您發佈的代碼actualy運行時,你不應該做pool.map(start_it()),因爲調用之前start_it結果傳遞給pool.map。相反,您必須通過start_it而沒有任何(),如pool.map(start_it)。你可能需要另一個參數(值傳遞給start_it)。

你可以嘗試下面的例子,這似乎適用於我。

import json 
import multiprocessing.pool 
import time 
import urllib2 

def run(no): 
    for n in range(3): 
     f = urllib2.urlopen("http://time.jsontest.com") 
     data = json.loads(f.read()) 
     f.close() 
     print("thread %d: %s" % (no, data)) 
     time.sleep(1) 

pool = multiprocessing.pool.ThreadPool(3) 
pool.map(run, range(3)) 

你也可以使用multiprocess.Process,例如:

import multiprocessing 
import time 
import os 

def run(jobno): 
    for n in range(3): 
     print("job=%d pid=%d" % (jobno, os.getpid())) 
     time.sleep(1) 

jobs = [] 
for n in range(3): 
    p = multiprocessing.Process(target=run, args=[n]) 
    jobs.append(p) 

map(lambda x: x.start(), jobs) 
map(lambda x: x.join(), jobs) 

輸出示例:在multiprocessing模塊下使用過程而不是線程,這是真正的平行

job=0 pid=18347 
job=1 pid=18348 
job=2 pid=18349 
job=0 pid=18347 
job=2 pid=18349 
job=1 pid=18348 
job=2 pid=18349 
job=0 pid=18347 
job=1 pid=18348 

一切。請注意,可能存在一些問題(與在同一進程下將它們作爲線程運行)。

+0

嗨我編輯我的代碼,現在它的作品。你在下面看到它。 –

相關問題