用urllib2多处理无用?

2024-04-24 07:40:30 发布

您现在位置:Python中文网/ 问答频道 /正文

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

你能用多处理来加速url调用吗?或者瓶颈不是网络适配器之类的东西?例如,我不知道urllib2 open方法的哪个部分可以并行化,也不知道它应该如何工作。。。

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

 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]

Tags: inselfjsonurlforfoowwwcount
3条回答

这要看情况!你是在联系不同的服务器,传输的文件是小文件还是大文件,你是否在等待服务器回复或传输数据时浪费了很多时间,。。。

通常,多处理涉及一些开销,因此您希望确保通过并行化工作获得的加速比开销本身更大。

另一点:网络和I/O绑定的应用程序在异步I/O和事件驱动体系结构中工作得更好,而不是线程或多处理,因为在这些应用程序中,大部分时间都花在等待I/O和不进行任何计算上。

对于您的特定问题,我将尝试通过使用TwistedgeventTornado或任何其他不使用线程来并行连接的网络框架来实现解决方案。

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

又来了一个关于吉尔的讨论。好吧,事情是这样的。使用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())

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

相关问题 更多 >