Skip to main content
 首页 » 编程设计

python之从 Eventlet GreenPile 对象中检索数据,可能与迭代器相关

2025年05月04日7grandyang

我目前正在修改我前段时间制作的一个简单的监控脚本,它基本上是:

构建一个字典列表,其中包含

  • 网站网址
  • 响应时间(默认设置为无)
  • 它返回的数据(默认设置为无)

查询 (GET) 列表中的每个 URL,并用相关数据填充“时间”和“数据”字段。

将结果存储在数据库中。

该脚本过去工作正常,但随着要监视的 URL 列表的增加,完成所有查询所需的时间对我来说变得太长了。

我的解决方案是修改脚本以并发方式获取 URL。为此,我选择使用 eventlet , 因为 this example文档中的内容几乎完全符合我的要求。

要注意的是,因为我的 URL 列表包含字典,所以我不能使用 pool.imap() 来遍历我的列表。 (据我所知)

Eventlet 文档有另一个类似的示例*,它使用 GreenPile 对象生成作业,似乎我可以使用它来启动我的 URL 获取功能,但我似乎无法检索该线程的结果。

这是我的测试代码:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import eventlet 
from eventlet.green import urllib2 
 
 
urls = [{'url': 'http://www.google.com/intl/en_ALL/images/logo.gif', 'data': None}, 
{'url': 'http://www.google.com', 'data': None}] 
 
 
def fetch(url): 
    return urllib2.urlopen(url).read() 
 
 
pool = eventlet.GreenPool() 
pile = eventlet.GreenPile(pool) 
 
 
for url in urls: 
    pile.spawn(fetch, url['url']) #can I get the return of the function here? 
 
#or 
for url in urls: 
    url['data'] = ??? #How do I get my data back? 
 
#Eventlet's documentation way 
data = "\n".join(pile) 

据我所知,pile 是一个可迭代对象,因此我可以遍历它,但我无法通过索引访问它的内容,这是否正确?

那么,我如何(可能?)直接填写我的 urls 列表?另一种解决方案可以是构建一个“扁平”的 url 列表,另一个包含 url、响应时间和数据的列表,并在第一个列表上使用 pool.imap() 并用它填充第二个列表,但是我宁愿保留我的词典列表。

*我不能使用此帐户发布超过 3 个链接,请参阅 eventlet 文档中的“设计模式 - 调度模式”页面。

请您参考如下方法:

您可以遍历 GreenPile,但您需要从 fetch 中返回一些内容,这样您得到的不仅仅是响应。我修改了示例,以便 fetch 返回一个元组,即 url 和响应主体。

urls 变量现在是 urls(string) 到数据(None 或 string)的字典。继续迭代 GreenPile,直到没有更多任务为止。迭代应该在调用 spawn

的同一线程中完成
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import eventlet 
from eventlet.green import urllib2 
 
 
#Change to map urls to the data found at them 
urls = {'http://www.google.com/intl/en_ALL/images/logo.gif': None, 
'http://www.google.com' :None} 
 
 
def fetch(url): 
    #return the url and the response 
    return (url, urllib2.urlopen(url).read()) 
 
 
pool = eventlet.GreenPool() 
pile = eventlet.GreenPile(pool) 
 
 
for url in urls.iterkeys(): 
    pile.spawn(fetch, url) #can I get the return of the function here? - No 
 
for url,response in pile: 
    #stick it back into the dict 
    urls[url] = response 
 
for k,v in urls.iteritems(): 
    print '%s - %d bytes' % (k,len(v))