为什么我不能加速在python中使用多线程爬行?

时间:2015-08-21 10:39:20

标签: python multithreading performance

在下方,您会看到我的履带式蓝图。我以为我可以通过多线程加速它,但我不能。通常,当我加载页面时,网络服务器很慢,然后抓取另一个加载多线程加载速度更快的网页会很不错。但它并不快。为什么呢?

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

4 个答案:

答案 0 :(得分:2)

您需要提供pool.map()可迭代的

此时您正在运行start_it(),它基本上会一个接一个地运行您的所有呼叫。我不知道您正在使用的ThreadPool的实现方式,但您可能需要执行以下操作:

pool.map(get_urls, list_of_urls)

答案 1 :(得分:0)

不要离题,但异步IO也是你问题的理想选择。您可以使用最近添加到python 3.4的名为asyncio的神奇库。对于旧版本,您可以使用trolliusTwisted

答案 2 :(得分:0)

如果您发布的代码实际运行,则不应该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)

示例输出:

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

multiprocessing模块下的所有内容都使用进程而不是真正并行的线程。请注意,可能存在一些问题(而不是在同一进程中将它们作为线程运行)。

答案 3 :(得分:-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()