Pythonリクエストモジュールを使用して試す/除外する正しい方法?


418
try:
    r = requests.get(url, params={'s': thing})
except requests.ConnectionError, e:
    print e #should I also sys.exit(1) after this?

これは正しいです?これを構造化するより良い方法はありますか?これは私のすべての拠点をカバーしますか?


回答:


795

Requests exception docsをご覧ください。要するに:

ネットワークの問題(DNSの失敗、接続の拒否など)が発生した場合、リクエストはConnectionError例外を発生させます。

まれに無効なHTTP応答が発生した場合、リクエストはHTTPError例外を発生させます。

リクエストがタイムアウトすると、Timeout例外が発生します。

リクエストが設定された最大リダイレクト数を超えると、TooManyRedirects例外が発生します。

Requestsが明示的に発生させるすべての例外は、から継承しrequests.exceptions.RequestExceptionます。

あなたの質問に答えるために、あなたが示すものはあなたのすべての基地をカバーするわけではありません。接続関連のエラーのみをキャッチし、タイムアウトしたエラーはキャッチしません。

例外をキャッチしたときに行うことは、実際にはスクリプト/プログラムの設計次第です。終了してもよいですか?続行してもう一度お試しいただけますか?エラーが致命的で続行できない場合は、はい。SystemExitを発生させることでプログラムを中止できます(エラーを出力してを呼び出すための優れた方法sys.exit)。

すべてのケースを処理する基本クラスの例外をキャッチすることもできます。

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.RequestException as e:  # This is the correct syntax
    raise SystemExit(e)

または、それらを別々にキャッチして、さまざまなことを行うことができます。

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.Timeout:
    # Maybe set up for a retry, or continue in a retry loop
except requests.exceptions.TooManyRedirects:
    # Tell the user their URL was bad and try a different one
except requests.exceptions.RequestException as e:
    # catastrophic error. bail.
    raise SystemExit(e)

以下のようクリスチャンは指摘しました:

httpエラー(例:401 Unauthorized)で例外を発生させたい場合は、を呼び出すことができますResponse.raise_for_status。これは発生しますHTTPError応答がHTTPエラーだった場合は、。

例:

try:
    r = requests.get('http://www.google.com/nothere')
    r.raise_for_status()
except requests.exceptions.HTTPError as err:
    raise SystemExit(err)

印刷されます:

404 Client Error: Not Found for url: http://www.google.com/nothere

11
リクエストライブラリの詳細、および一般的な例外キャッチを処理するための非常に良い答えです。
ブライアンピーターソン2014年

10
下にあるurllib3ライブラリのバグのためsocket.timeout、タイムアウトを使用している場合は、例外をキャッチする必要があることに注意してください:github.com/kennethreitz/requests/issues/1236
jb。

15
今後のコメントリーダー:これはリクエスト2.9(urllib3 1.13をバンドル)で修正されました
RazerM

14
httpエラー(例:401 Unauthorized)で例外を発生させたい場合は、Response.raise_for_statusを呼び出すことができます。応答がhttpエラーの場合、HTTPErrorが発生します。
クリスチャンロング

5
リクエストWebサイトの例外リストは完全ではありません。あなたはここで完全なリストを読むことができます
Epoc 2017年

87

明確にするためのもう1つの提案。特定のエラーから一般的なエラーのスタックに移動して、目的のエラーをキャッチすることをお勧めします。そのため、特定のエラーは一般的なエラーによってマスクされません。

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)

Http Error: 404 Client Error: Not Found for url: http://www.google.com/blahblah

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)     

OOps: Something Else 404 Client Error: Not Found for url: http://www.google.com/blahblah

この投稿も有効な構文ですか?
ScipioAfricanus

@ScipioAfricanusはい。
andrea

10

例外オブジェクトには元の応答も含まe.responseれています。サーバーからの応答でエラー本文を確認する必要がある場合に役立ちます。例えば:

try:
    r = requests.post('somerestapi.com/post-here', data={'birthday': '9/9/3999'})
    r.raise_for_status()
except requests.exceptions.HTTPError as e:
    print (e.response.text)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.