我正在使用金字塔构建网站,我想从其他网站获取一些数据。因为可能有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的建议,但我找不到在文档中提取多个页面的示例。
我还尝试了来自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'
上次更新中的TypeError
可能是早期尝试使用gevent进行monkeypatch并且没有正确重新启动pserve。一旦我重新启动了一切,它就能正常工作。经验教训。
答案 0 :(得分:2)
有多种方法可以做你想做的事:
gevent
线程,并明确地将所有打开网址的作业分配给该线程,然后执行已完成的urlopen
请求。gevent
,这种框架无法通过神奇地对您的代码进行绿化,而不会起作用。pycurl
。gevent
构建服务器,或找到适合您的Web服务和Web客户端需求的其他框架。您可以通过先加载gevent
来模拟最后一个而不更改框架,并让它对您的线程进行monkeypatch,从而强制您的现有线程服务器框架成为gevent
服务器。但这可能不起作用,或者主要是工作但偶尔会失败,或工作但速度要慢得多......真的,使用一个设计为gevent
的框架 - 友好(或至少是绿色友好的)是一个更好的主意,如果这就是你想要的方式。
你提到其他人推荐requests
。您找不到文档的原因是requests
中的内置异步代码已被删除。请参阅an older version了解其使用方法。它现在作为单独的库grequests
提供。但是,它通过隐式包装requests
和gevent
来工作,因此它与您自己完全相同的问题。
(还有其他原因可以使用requests
代替urllib2
,如果您想gevent
,则使用grequests
比使用{{1}}更容易。
答案 1 :(得分:1)
尝试部署Web应用程序时,我遇到过与gevent类似的问题。您可以做的事情是最简单的麻烦是使用在gevent上运行的WSGI部署;示例包括gUnicorn,uWSGI或gevent的内置WSGI服务器之一。金字塔应该有一种使用备用部署的方法。如果代码的大部分依赖于gevent,那么只使用在gevent上运行的服务器也会更容易。
所以,基本上是上述答案的最后一个子弹。