Python のリクエスト モジュールはシンプルでエレガントですが、気になる点が 1 つあります。次のようなメッセージで、requests.exception.ConnectionErrorが発生する可能性があるのです。
Max retries exceeded with url: ...
これは、リクエストがデータに複数回アクセスを試みることができることを意味します。しかし、ドキュメントのどこにもこの可能性について言及されていません。ソース コードを調べても、既定値 (おそらく 0) を変更できる場所は見つかりませんでした。
では、リクエストの最大再試行回数を何らかの方法で設定することは可能でしょうか?
ベストアンサー1
これにより、max_retries が変更されるだけでなく、すべてのhttp://アドレスへのリクエストを一定期間スリープさせてから再試行する (合計 5 回)バックオフ戦略も有効になります。
import requests
from requests.adapters import HTTPAdapter, Retry
s = requests.Session()
retries = Retry(total=5,
backoff_factor=0.1,
status_forcelist=[ 500, 502, 503, 504 ])
s.mount('http://', HTTPAdapter(max_retries=retries))
s.get('http://httpstat.us/500')
に従ってドキュメントRetry
: backoff_factor が0.1の場合、 sleep() は再試行の間に [0.05 秒、0.1 秒、0.2 秒、0.4 秒、...] の間スリープします。返されたステータス コードが500、502、503、または504の場合も再試行が強制されます。
Retry
よりきめ細かな制御を可能にするその他のさまざまなオプション:
- total – 許可する再試行の合計回数。
- connect – 接続関連のエラーを何回再試行するか。
- 読み取り– 読み取りエラーが発生した場合に再試行する回数。
- リダイレクト– 実行するリダイレクトの数。
- method_whitelist – 再試行する必要がある大文字の HTTP メソッド動詞のセット。
- status_forcelist – 再試行を強制する必要がある HTTP ステータス コードのセット。
- backoff_factor – 試行間に適用するバックオフ係数。
- raise_on_redirect – リダイレクトの数が上限に達した場合に、エラーを発生させるか、または3xx
MaxRetryError
範囲の応答コードで応答を返すかを指定します。 - raise_on_status – raise_on_redirectと同様の意味: ステータスがstatus_forcelist の範囲内にあり、再試行が失敗した場合に、例外を発生させるか、応答を返すかを指定します。
注意
:
raise_on_status
は比較的新しいため、urllib3 や request のリリースにはまだ組み込まれていません。raise_on_status
キーワード引数は、Python バージョン 3.6 でようやく標準ライブラリに組み込まれたようです。
特定の HTTP ステータス コードでリクエストを再試行するには、status_forcelistを使用します。たとえば、status_forcelist=[503]はステータス コード503 (サービス利用不可)で再試行します。
デフォルトでは、再試行は次の条件の場合にのみ実行されます。
- プールから接続できませんでした。
TimeoutError
HTTPException
発生しました ( Python 3 のhttp.clientまたはhttplibから)。これは、URL またはプロトコルが正しく形成されていないなどの低レベルの HTTP 例外であると思われます。SocketError
ProtocolError
これらはすべて、通常の HTTP 応答の受信を妨げる例外であることに注意してください。通常の応答が生成された場合、再試行は行われません。 status_forcelistを使用しない場合、ステータス 500 の応答であっても再試行されません。
リモート API または Web サーバーを操作する際に、より直感的に動作するようにするには、上記のコード スニペットを使用します。このコード スニペットは、ステータス 500、502、503、および 504 で再試行を強制します。これらはすべてWebでは珍しくなく、十分なバックオフ期間があれば (おそらく) 回復可能です。