Gevent プール内で数十の HTTP リクエストを実行しています。
目標は、リクエストが失敗した場合に 1 回だけ再試行することです。それ以外の場合は、例外をスローする必要があります。
HTTP リクエストが失敗した場合に 1 回の再実行をサポートする at プールを使用して 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
ますspawn_greenlet
か? - 私がこれを理解している限り
gevent.joinall(greenlets)
、マップによって返されたグリーンレットのみに参加します。例外がある場合、元の greenlet は によって返された新しいものに置き換えられretry_once
ますか? そうでない場合、追加の greenlet がまだ実行されていても処理は続行されますか? その場合、すべての greenlet が終了するのをどのように待つことができますか?
Gevent のドキュメントは非常に少なく、これがかなり一般的な使用例であるにも関わらず、これをドキュメント化した Web のリソースは他にないようです。したがって、私はこれがあまりにも局所的な質問だとは考えていません。