Gevent通过非阻塞joinall()增量处理
在这里,我想对我的设置做一些修改。
我希望在向我的服务器发出一个请求时,能够同时从多个API调用中获取响应。我想把这些API调用的结果合并起来,然后作为一个响应返回给前端。到这里为止,基本上所有的内容都和gevent文档中的例子差不多。不过这里有个关键点,我想以增量的方式返回响应,也就是说,如果第一个API调用返回了结果,我就会立即把这个结果返回给前端,然后再等待其他API调用的结果,并把它们也在同一个请求中返回给前端。
我尝试通过代码来实现这个功能,但我不知道该如何进行设置。gevent的.joinall()
和.join()
会一直阻塞,直到所有的绿色线程(greenlets)都完成响应。
有没有什么方法可以在这个设置中继续使用gevent呢?
我这里使用的代码可以在这个链接找到:https://bitbucket.org/denis/gevent/src/tip/examples/concurrent_download.py。在最后的语句中,.joinall()
会等待所有的URL都完成响应,我希望它能够非阻塞,这样我就可以在回调函数print_head()中处理响应,并以增量的方式返回它们。
#!/usr/bin/python
# Copyright (c) 2009 Denis Bilenko. See LICENSE for details.
"""Spawn multiple workers and wait for them to complete"""
urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org']
import gevent
from gevent import monkey
# patches stdlib (including socket and ssl modules) to cooperate with other greenlets
monkey.patch_all()
import urllib2
def print_head(url):
print ('Starting %s' % url)
data = urllib2.urlopen(url).read()
print ('%s: %s bytes: %r' % (url, len(data), data[:50]))
jobs = [gevent.spawn(print_head, url) for url in urls]
gevent.joinall(jobs)
1 个回答
1
如果你想从多个绿色线程(greenlets)中收集结果,那么你需要修改一下 print_head()
这个函数,让它返回结果。然后你可以使用 .get()
方法来把所有结果收集起来。
把这个放在 joinall()
之后:
total_result = [x.get() for x in jobs]
其实在这种情况下,joinall()
这个步骤是可以省略的。
如果 print_head()
的样子是这样的:
def print_head(url):
print ('Starting %s' % url)
return urllib2.urlopen(url).read()
那么 total_result
就会是一个大小为3的列表,里面包含了所有请求的响应。