使用urllib2进行多处理无用?

dor*_*vak 9 python urllib2 multiprocessing gil

我最近尝试加速一个小工具(使用urllib2向多处理模块发送请求到(非官方)twitter-button-count-url(> 2000 urls)并解析它的结果)(并且它工人池).我在这里阅读了几个关于多线程的讨论(与标准的非线程版本相比减慢了整个过程)和多处理,但我找不到一个(可能非常简单)问题的答案:

你可以通过多处理加速网址调用,还是像网络适配器这样的瓶颈?我不知道urllib2-open-method的哪一部分可以并行化,以及它应该如何工作......

编辑:这是我想要加速的请求和当前的多处理设置:

 urls=["www.foo.bar", "www.bar.foo",...]
 tw_url='http://urls.api.twitter.com/1/urls/count.json?url=%s'

 def getTweets(self,urls):
    for i in urls:
        try:
            self.tw_que=urllib2.urlopen(tw_url %(i))
            self.jsons=json.loads(self.tw_que.read())
            self.tweets.append({'url':i,'date':today,'tweets':self.jsons['count']})
        except ValueError:
            print ....
            continue
    return self.tweets 

 if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)            
    result = [pool.apply_async(getTweets(i,)) for i in urls]
    [i.get() for i in result]
Run Code Online (Sandbox Code Playgroud)

Chr*_*rle 7

啊,这是另一个关于GIL的讨论.好吧,这就是事情.使用urllib2获取内容主要是 IO绑定的.当任务受IO限制时,本机线程和多处理将具有相同的性能(线程仅在CPU受限时成为问题).是的,你可以加快速度,我自己使用python线程和10个下载程序线程完成.

基本上,您使用生产者 - 消费者模型,其中一个线程(或进程)生成要下载的URL,并且N个线程(或进程)从该队列中消耗并向服务器发出请求.

这是一些伪代码:

# Make sure that the queue is thread-safe!!

def producer(self):
    # Only need one producer, although you could have multiple
    with fh = open('urllist.txt', 'r'):
        for line in fh:
            self.queue.enqueue(line.strip())

def consumer(self):
    # Fire up N of these babies for some speed
    while True:
        url = self.queue.dequeue()
        dh = urllib2.urlopen(url)
        with fh = open('/dev/null', 'w'): # gotta put it somewhere
            fh.write(dh.read())
Run Code Online (Sandbox Code Playgroud)

现在,如果您正在下载非常的数据块(数百MB)并且单个请求完全使带宽饱和,那么运行多个下载是没有意义的.您(通常)运行多次下载的原因是请求很小并且具有相对较高的延迟/开销.


Den*_*nko 6

看看gevent,特别是在这个例子中:concurrent_download.py.它将比多处理和多线程处理速度快得多+它可以轻松处理数千个连接.