Python 使用带棱锥的gevent

Python 使用带棱锥的gevent,python,pyramid,gevent,urlopen,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.u

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

我已经读到我需要在做任何事情之前先做修补,但我不确定哪里是合适的地方。此外,这是否是pserve特有的问题?当我搬家时,我需要重新解决这个问题吗?或者有没有一种方法可以在没有gevent的情况下处理这个用例(只是urlopen)?我已经看到了一些建议,但是我找不到在文档中获取多个页面的示例

更新1: 我还尝试了来自的eventlet(几乎直接复制自此eventlet):

然而,当我调用
fetch\u multiple
时,我得到了
TypeError:request()得到了一个意外的关键字参数“return\u response”

更新2:
上次更新中出现的
TypeError
可能是由于以前尝试使用gevent安装monkeypatch,但未正确重新启动pserve造成的。一旦我重新启动所有程序,它就会正常工作。吸取的教训。

有多种方法可以满足您的需求:

  • 创建一个专用的
    gevent
    线程,并显式地将所有URL打开作业分派给该线程,然后该线程将执行gevented
    urlopen
    请求
  • 使用线程而不是greenlet。运行50个线程不会对任何现代操作系统征税
  • 使用线程池和队列。一次下载50次,而不是一次下载8次,通常没有多大好处(你的浏览器可能就是这样)
  • 使用不同的异步框架,而不是
    gevent
    ,一个通过神奇地将代码绿色化而无法工作的框架
  • 使用具有自己的非魔术异步支持的库,如
    pycurl
  • 不要混合和匹配不兼容的框架,也可以围绕
    gevent
    构建服务器,或者找到其他既能满足web服务需求又能满足web客户端需求的框架
您可以通过先加载
gevent
来模拟最后一个,而无需更改框架,并让它monkeypatch您的线程,强制现有的线程服务器框架成为
gevent
服务器。但这可能不起作用,或者大部分起作用但偶尔会失败,或者起作用但速度要慢得多……真的,如果你想这样做的话,使用一个设计为
gevent
-友好(或者至少是greenlet友好)的框架是一个更好的主意

您提到其他人建议了
请求
。找不到文档的原因是,
请求
中的内置异步代码已被删除。看,它是如何使用的。它现在作为一个单独的库提供。但是,它的工作原理是使用
gevent
隐式包装
请求
,因此它的问题与您自己的问题完全相同


(使用
请求
而不是
urlib2
还有其他原因,如果您想
gevent
,使用
grequests
比自己做更容易。)

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

  • 创建一个专用的
    gevent
    线程,并显式地将所有URL打开作业分派给该线程,然后该线程将执行gevented
    urlopen
    请求
  • 使用线程而不是greenlet。运行50个线程不会对任何现代操作系统征税
  • 使用线程池和队列。一次下载50次,而不是一次下载8次,通常没有多大好处(你的浏览器可能就是这样)
  • 使用不同的异步框架,而不是
    gevent
    ,一个通过神奇地将代码绿色化而无法工作的框架
  • 使用具有自己的非魔术异步支持的库,如
    pycurl
  • 不要混合和匹配不兼容的框架,也可以围绕
    gevent
    构建服务器,或者找到其他既能满足web服务需求又能满足web客户端需求的框架
您可以通过先加载
gevent
来模拟最后一个,而无需更改框架,并让它monkeypatch您的线程,强制现有的线程服务器框架成为
gevent
服务器。但这可能不起作用,或者大部分起作用但偶尔会失败,或者起作用但速度要慢得多……真的,如果你想这样做的话,使用一个设计为
gevent
-友好(或者至少是greenlet友好)的框架是一个更好的主意

您提到其他人建议了
请求
。找不到文档的原因是,
请求
中的内置异步代码已被删除。看,它是如何使用的。它现在作为一个单独的库提供。但是,它的工作原理是使用
gevent
隐式包装
请求
,因此它的问题与您自己的问题完全相同


(使用
请求
而不是
urllib2
还有其他原因,如果您想
gevent
,使用
grequests
比自己做更容易。)

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


因此,基本上是上述答案的最后一个要点。

我在尝试部署web应用程序时遇到了与gevent类似的问题。你所能做的事是最简单的
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)