web-dev-qa-db-ja.com

失敗したときにurllib2.requestを再試行する方法は?

いつ urllib2.requestタイムアウトに達しました、urllib2.URLError例外が発生します。接続の確立を再試行するPythonの方法は何ですか?

30
iTayb

retry デコレータを使用します。他にもありますが、これはかなりうまくいきます。使い方は次のとおりです。

@retry(urllib2.URLError, tries=4, delay=3, backoff=2)
def urlopen_with_retry():
    return urllib2.urlopen("http://example.com")

これは、URLErrorが発生した場合に関数を再試行します。上記のリンクでパラメータのドキュメントを確認しますが、基本的には最大4回再試行し、指数バックオフ遅延は毎回2倍になります。 3秒、6秒、12秒。

58
jterrace

これに特化したライブラリがいくつかあります。

1つは backoff で、特に機能的な感性で設計されています。デコレータには、連続する遅延値を生成するジェネレータを返す任意の呼び出し可能オブジェクトが渡されます。最大再試行時間が32秒の単純な指数バックオフは、次のように定義できます。

@backoff.on_exception(backoff.expo,
                      urllib2.URLError,
                      max_value=32)
def url_open(url):
    return urllib2.urlopen("http://example.com")

もう1つは retrying です。これは非常によく似た機能を備えていますが、事前定義されたキーワード引数を使用して再試行パラメーターを指定するAPIです。

6
bgreen-litl

タイムアウト時に再試行するには、例外をキャッチすることができます @ Karl Barkerがコメントで提案

assert ntries >= 1
for _ in range(ntries):
    try:
        page = urlopen(request, timeout=timeout)
        break # success
    except URLError as err:
        if not isinstance(err.reason, socket.timeout):
           raise # propagate non-timeout errors
else: # all ntries failed 
    raise err # re-raise the last timeout error
# use page here
3
jfs