概要
requestsは以下のようにResponse.raise_for_status()
というメソッドを使うとレスポンスのステータスコードが400系や500系だった場合に、例外を送出することができる。
bad_r = requests.get('http://httpbin.org/status/404')
bad_r.raise_for_status()
また、requestsが送出する例外は、全てrequests.exceptions.RequestException
を継承しているということが公式ドキュメントに明記されている。
docs.python-requests.org
従って、以下のようなコードを書くと、レスポンスが不正だった場合にエラー内容をログに出力することができる。
bad_r = requests.get("http://httpbin.org/status/404") try: bad_r.raise_for_status() except RequestException: logger.exception("request failed.")
しかし、上記のコードではスタックトレースには以下のようなログしか出力されない。
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://httpbin.org/status/404
これだけだと、例えばAPIが返したJSONのエラー情報を出力したいという場合に困る。
従って、レスポンスボディを出力できないのかと思い調べてみた。
結論
RequestException
はフィールドにResponse
オブジェクトを保持しているので、以下のようにe.response.text
で例外オブジェクトからレスポンスボディを取得することができる。
bad_r = requests.get("http://httpbin.org/status/404") try: bad_r.raise_for_status() except RequestException as e: logger.exception("request failed. error=(%s)", e.response.text)
※ 以下のRequestException
のソースコードを読むと、フィールドにResponse
オブジェクトを保存していることが分かる。
docs.python-requests.org
検証
このAPIは例えば以下のような存在しないURLを叩くと404と一緒に以下のようなJSONのエラーメッセージが返ってくる。
https://dog.ceo/api/breeds/image/notfound
{"status":"error","message":"No route found for \"GET \/api\/breeds\/image\/notfound\" with code: 0","code":404}
このJSONを出力できることを確認する。
■検証用コード
import logging import requests from requests.exceptions import RequestException logger = logging.getLogger(__name__) response = requests.get("https://dog.ceo/api/breeds/image/notfound") try: response.raise_for_status() except RequestException as e: print(e.response.text)
■実行結果
コンソールに以下が出力された。
{"status":"error","message":"No route found for \"GET \/api\/breeds\/image\/notfound\" with code: 0","code":404}
以上