Pythonのrequestsライブラリで、Response Bodyが無いときに「json()」した場合などの動作を確認してみた

Pythonのrequestsライブラリで、Response Bodyが無いときに「json()」した場合などの動作を確認してみた

JSON形式でないときに「response.json()」をすると、「requests.exceptions.JSONDecodeError」が発生します。
Clock Icon2024.09.13

Pythonでrequestsライブラリをよく使います。利用先のAPIによっては、Response Bodyがあったり無かったりします。そこで毎回、「あれ? どんな動作するんだっけ……?」となりがちだったので、改めて確認してみました。

おすすめの方

  • Pythonのrequestsライブラリで、Response Bodyが無い場合の動作を知りたい方
  • Pythonのrequestsライブラリで、Response BodyがJSON以外の場合の動作を知りたい方

最初に結論

  • Response Bodyが無いとき、response.json()をすると、「requests.exceptions.JSONDecodeError」が発生する
  • Response BodyがあるけどJSON形式でないとき、response.json()をすると、「requests.exceptions.JSONDecodeError」が発生する

確認用のAPIをデプロイする

sam init

sam init \
    --runtime python3.11 \
    --name python-requests-test-api-sample \
    --app-template hello-world \
    --no-tracing \
    --no-application-insights \
    --structured-logging \
    --package-type Zip

テンプレートファイル

2つのAPIを作成します。

  • GET /not-response-body
  • GET /not-json-response-body
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: python-requests-test-api-sample

Globals:
  Function:
    Timeout: 3
    LoggingConfig:
      LogFormat: JSON

Resources:
  HelloWorld1Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world1/
      Handler: app.lambda_handler
      Runtime: python3.11
      Architectures:
      - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /not-response-body
            Method: get

  HelloWorld1FunctionLogGroup:
        Type: AWS::Logs::LogGroup
        Properties:
          LogGroupName: !Sub /aws/lambda/${HelloWorld1Function}

  HelloWorld2Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world2/
      Handler: app.lambda_handler
      Runtime: python3.11
      Architectures:
      - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /not-json-response-body
            Method: get

  HelloWorld2FunctionLogGroup:
        Type: AWS::Logs::LogGroup
        Properties:
          LogGroupName: !Sub /aws/lambda/${HelloWorld2Function}

Lambdaコード

GET /not-response-body 用のLambda

import json

def lambda_handler(event, context):
    return {
        "statusCode": 200,
    }

GET /not-json-response-body 用のLambda

import json

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": "not json message",
    }

デプロイ

sam deploy \
    --guided \
    --region ap-northeast-1 \
    --stack-name python-requests-test-api-sample-stack

実験用のPythonスクリプトを用意する

app.py
import requests

ENDPOINST = "https://xxx.execute-api.ap-northeast-1.amazonaws.com/Prod/"

PATH1 = "/not-response-body"
PATH2 = "/not-json-response-body"

def main():
    print("### get_not_response_body()")
    get_not_response_body()

    print("\n")
    print("### get_not_json_response_body()")
    get_not_json_response_body()

def get_not_response_body():
    response = requests.get(ENDPOINST + PATH1)
    print(f"status code: {response.status_code}")
    print(f"text type: {type(response.text)}")
    print(f"text length: {len(response.text)}")
    print(f"text: {response.text}")

    try:
        xxx = response.json()
    except requests.exceptions.JSONDecodeError as e:
        # この例外が発生する
        print(f"json decode error: {e}")

def get_not_json_response_body():
    response = requests.get(ENDPOINST + PATH2)
    print(f"status code: {response.status_code}")
    print(f"text type: {type(response.text)}")
    print(f"text length: {len(response.text)}")
    print(f"text: {response.text}")

    try:
        xxx = response.json()
    except requests.exceptions.JSONDecodeError as e:
        # この例外が発生する
        print(f"json decode error: {e}")

if __name__ == "__main__":
    main()

実行する

「requests.exceptions.JSONDecodeError」が発生しました。また、response.textは空のstrになっていました(Noneではない)。

### get_not_response_body()
status code: 200
text type: <class 'str'>
text length: 0
text: 
json decode error: Expecting value: line 1 column 1 (char 0)

### get_not_json_response_body()
status code: 200
text type: <class 'str'>
text length: 16
text: not json message
json decode error: Expecting value: line 1 column 1 (char 0)

さいごに

エラーハンドリングは大切なので、しっかり対応していきたいですね。どなたかの参考になれば幸いです。

参考

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.