我在Gevent池中做了几十个HTTP请求。
目标是在失败时重试一次请求,但只返回一次。否则,它应该抛出异常。
我如何在支持重新运行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)
joinall(greenlets)
内但在调用do_request
事件处理程序之前发生异常后,retry_once
方法是否有可能返回?is_retry
处的spawn_greenlet
kwarg?gevent.joinall(greenlets)
只加入地图返回的greenlets。如果有异常,原始greenlet是否被retry_once
返回的新greenlet替换?如果没有,即使其他greenlet仍在运行,处理是否仍在继续?在这种情况下,我怎么能等待所有的greenlets完成?Gevent文档非常稀缺,网络上似乎没有其他资源记录这一点,即使这是一个相当常见的用例。因此,我不认为这是一个太局部化的问题。
答案 0 :(得分:1)
不要使用spawn / link / link_exception来重试。只需使用普通的Python:
def do_something_with_retry(*args):
try:
return do_something(*args)
except Exception:
return do_something(*args)
此外,gevent.pool.Pool.map会自动在给定池中生成greenlet,您不必这样做。
pool = Pool(10)
pool.map(do_something_with_retry, [1, 2, 3])
现在,您只需要实现do_something()
,这可以是普通的Python /请求代码:
def do_something(*args):
return requests.get('http://gevent.org')
玩得开心!