使用gevent与金字塔

时间:2013-01-11 20:34:04

标签: python pyramid gevent urlopen

我正在使用金字塔构建网站,我想从其他网站获取一些数据。因为可能有50多个urlopen来电,所以我想用gevent来加快速度。

这是我到目前为止使用gevent的原因:

import urllib2    
from gevent import monkey; monkey.patch_all()
from gevent import pool

gpool = gevent.pool.Pool()

def load_page(url):
    response = urllib2.urlopen(url)
    html = response.read()
    response.close()
    return html

def load_pages(urls):
    return gpool.map(load_page, urls)

正在运行pserve development.ini --reload

NotImplementedError: gevent is only usable from a single thread

我已经读过,我需要在其他任何事情之前修补补丁,但我不确定哪个地方适合那个地方。此外,这是一个特定于问题的问题吗?当我搬到mod_wsgi时,我是否需要重新解决这个问题?或者有没有办法处理这个用例(只是urlopen)没有gevent?我见过requests的建议,但我找不到在文档中提取多个页面的示例。

更新1:

我还尝试了来自this SO question的eventlet(几乎直接从此eventlet复制example):

import eventlet
from eventlet.green import urllib2

def fetch(url):
    return urllib2.urlopen(url).read()

def fetch_multiple(urls):
    pool = eventlet.GreenPool()
    return pool.imap(fetch, urls)

但是,当我致电fetch_multiple时,我正在TypeError: request() got an unexpected keyword argument 'return_response'

更新2:

上次更新中的TypeError可能是早期尝试使用gevent进行monkeypatch并且没有正确重新启动pserve。一旦我重新启动了一切,它就能正常工作。经验教训。

2 个答案:

答案 0 :(得分:2)

有多种方法可以做你想做的事:

  • 创建一个专用的gevent线程,并明确地将所有打开网址的作业分配给该线程,然后执行已完成的urlopen请求。
  • 使用线程代替greenlets。运行50个线程不会对任何现代操作系统征税。
  • 使用线程池和队列。同时进行50次下载通常没有多大优势,而不是一次只做8次(如浏览器可能的那样)。
  • 使用不同的异步框架而不是gevent,这种框架无法通过神奇地对您的代码进行绿化,而不会起作用。
  • 使用具有自己的非魔法异步支持的库,例如pycurl
  • 不是混合和匹配不兼容的框架,而是围绕gevent构建服务器,或找到适合您的Web服务和Web客户端需求的其他框架。

您可以通过先加载gevent来模拟最后一个而不更改框架,并让它对您的线程进行monkeypatch,从而强制您的现有线程服务器框架成为gevent服务器。但这可能不起作用,或者主要是工作但偶尔会失败,或工作但速度要慢得多......真的,使用一个设计为gevent的框架 - 友好(或至少是绿色友好的)是一个更好的主意,如果这就是你想要的方式。

你提到其他人推荐requests。您找不到文档的原因是requests中的内置异步代码已被删除。请参阅an older version了解其使用方法。它现在作为单独的库grequests提供。但是,它通过隐式包装requestsgevent来工作,因此它与您自己完全相同的问题。

(还有其他原因可以使用requests代替urllib2,如果您想gevent,则使用grequests比使用{{1}}更容易。

答案 1 :(得分:1)

尝试部署Web应用程序时,我遇到过与gevent类似的问题。您可以做的事情是最简单的麻烦是使用在gevent上运行的WSGI部署;示例包括gUnicorn,uWSGI或gevent的内置WSGI服务器之一。金字塔应该有一种使用备用部署的方法。如果代码的大部分依赖于gevent,那么只使用在gevent上运行的服务器也会更容易。

所以,基本上是上述答案的最后一个子弹。