繁体   English   中英

Gevent:重试greenlet一次

[英]Gevent: Retry greenlet once

我在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)
  • 我有一个更清晰的方法来获取greenlet函数的参数而不是通过异常参数吗?
  • 有没有一种可能性,即joinall(greenlets)内发生异常后返回方法do_request但之前retry_once事件处理程序被调用?
  • 有没有更简洁的方法来重新启动具有相同参数的greenlet,所以我不需要is_retry is_retry spawn_greenlet
  • 据我所知, gevent.joinall(greenlets)只加入map返回的greenlets。 当出现异常时,是否将原始greenlet替换为retry_once返回的新retry_once 如果没有,即使其他greenlet仍在运行,处理是否仍在继续? 在这种情况下,我怎么能等待所有的greenlets完成?

Gevent文档非常稀缺,网络中似乎没有其他资源记录这一点,即使这是一个相当常见的用例。 因此,我不认为这是一个太局部化的问题。

不要使用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')

玩得开心!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM