我在 Gevent 池中执行了几十个 HTTP 请求。
目标是在请求失败时重试一次,但只重试一次。否则,它应该抛出异常。
如果失败,我将如何使用 at pool 编写支持重新运行 HTTP 请求的 gevent 代码?
这种方法可行吗?
import requests
import gevent
from gevent.pool import Pool
pool = Pool(10)
def do_request(id):
r = requests.get('http://example.com/%u' % id)
if not r.status_code == 200:
raise RuntimeError(id)
def spawn_greenlet(id, is_retry=False):
if not is_retry:
g = gevent.spawn(id)
g.link_exception(retry_once)
else:
g = pool.spawn(id)
g.link_exception(raise_exception)
return g
def retry_once(greenlet):
return spawn_greenlet(greenlet.exception.args[0])
def raise_exception(greenlet):
if greenlet.exception:
raise greenlet.exception
raise RuntimeError('Unknown error in greenlet processing.')
greenlets = pool.map(spawn_greenlet, [1, 2, 3, 4, 5])
gevent.joinall(greenlets)
- 有没有比通过异常参数更简洁的方法来获取 greenlet 函数的参数?
joinall(greenlets)
在内部发生异常do_request
但在retry_once
调用事件处理程序之前,方法是否有可能返回?- 有没有更干净的方法来重新启动具有相同参数的greenlet,所以我不需要
is_retry
kwarg atspawn_greenlet
? - 据我了解,
gevent.joinall(greenlets)
仅加入 map 返回的greenlets。当出现异常时,是否将原始greenlet替换为返回的新greenletretry_once
?如果不是,即使额外的greenlets仍在运行,处理是否会继续?在那种情况下,我怎么能等待所有的greenlets完成呢?
Gevent 文档非常稀缺,而且网络上似乎没有其他资源可以记录这一点,尽管这是一个相当常见的用例。因此,我不认为这是一个过于本地化的问题。