1

我正在使用金字塔建立一个网站,我想从其他网站获取一些数据。因为可能有 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.

我已经读到我需要先修补猴子补丁,但我不确定合适的地方在哪里。另外,这是特定于 pserve 的问题吗?当我搬到mod_wsgi时,我需要重新解决这个问题吗?或者有没有办法在没有 gevent 的情况下处理这个用例(只是 urlopen)?我已经看到了有关请求的建议,但我在文档中找不到获取多个页面的示例。

更新1:

我还尝试了这个 SO question中的 eventlet (几乎直接从这个 eventlet示例中复制):

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。一旦我重新启动一切,它就可以正常工作。学过的知识。

4

2 回答 2

3

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

  • 创建一个专用gevent线程,并将所有打开 URL 的作业显式分派到该线程,然后该线程将执行 geventedurlopen请求。
  • 使用线程而不是greenlets。运行 50 个线程不会对任何现代操作系统造成负担。
  • 使用线程池和队列。同时进行 50 次下载而不是一次下载 8 次(就像您的浏览器可能那样)通常没有太大优势。
  • 使用不同的异步框架gevent,而不是通过神奇地绿化你的代码来工作。
  • 使用具有自己的非魔法异步支持的库,例如pycurl.
  • 与其混合和匹配不兼容的框架,还不如围绕它构建服务器gevent,或者找到一些其他框架同时满足您的 Web 服务和 Web 客户端的需求。

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

你提到其他人推荐过requests。您找不到文档的原因是内置的异步代码requests已被删除。请参阅旧版本,了解它的使用方式。它现在作为一个单独的库提供,grequests. 但是,它通过隐式包装requestswith来工作gevent,因此它与您自己这样做会有完全相同的问题。

(还有其他原因可以requests代替urllib2,如果您愿意,gevent使用它grequests比自己做更容易。)

于 2013-01-11T20:46:44.060 回答
2

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

因此,基本上是上述答案的最后一个项目符号。

于 2013-01-11T22:32:36.363 回答