自作APIとの通信をするPythonコードのメモ(requestsモジュール)

お疲れ様です。

今回はFastAPIで作成したAPIPythonコードからリクエストをかけてデータ取得するコードをざっくりとまとめました。

コード解説

コードは下記に残してありますので詳細を確認したい場合はご確認を。実際にGitHubに挙げているコードを見てもらった方がわかりやすいとは思います。
機能は自体はrequestsモジュールを使って実装しました。 github.com FastAPIのコードに関しては以前作成のものをベースにしています。必要があればこちらもご確認ください。 fallpoke-tech.hatenadiary.jp

各変数の中身は以下。

sample_data = {
    "last_name": ["Miyamoto", "Ishimori", "Takamidori", "Tominaga"],
    "age": [58, 57, 58, 58], 
    "part": ["Vo./Gt.", "Gt.", "Ba.", "Dr."]
}
API_URL = "http://localhost:8000/"

GETメソッドのテスト

@app.get("/sample_data")
def get_sample_data() -> dict:
    """サンプルデータの内容を取得するAPI
    """
    return sample_data
# データの取得
res = requests.get(API_URL+"/sample_data")

単純にURLを指定してデータを取得する形です。実行するとsample_dataの中身がそのまま取得されます。 responseデータの中身はjson形式で返ってきているのでres.json()で確認できます。
出力は以下。

{'last_name': ['Miyamoto', 'Ishimori', 'Takamidori', 'Tominaga'],  
 'age': [58, 57, 58, 58],  
 'part': ['Vo./Gt.', 'Gt.', 'Ba.', 'Dr.']}  

POSTメソッドのテスト

@app.post("/sample_data")
def get_sample_data_add(obj: AddData) -> dict:
    """受信したデータを追加したサンプルデータの内容を取得するAPI
    """
    add_data = obj.model_dump()
    print(add_data)
    
    sample_data_new = add_data | sample_data
    
    global sample_df
    sample_df = pd.DataFrame(sample_data_new)
    
    return sample_data_new
# データを追加+追加後のデータを取得
submit_data = {"first_name": ["Hiroji", "Toshiyuki", "Seiji", "Yoshiyuki"]}

res = requests.post(API_URL+"/sample_data", json=submit_data)

次にPOSTメソッド。追加データ(submit_data)をAPI側に渡してsample_dataに追加した状態のものをresponseとして返す形です。 こちらもres.json()で中身を確認できます。
出力は以下。

{'first_name': ['Hiroji', 'Toshiyuki', 'Seiji', 'Yoshiyuki'],  
 'last_name': ['Miyamoto', 'Ishimori', 'Takamidori', 'Tominaga'],  
 'age': [58, 57, 58, 58],  
 'part': ['Vo./Gt.', 'Gt.', 'Ba.', 'Dr.']}  

GETメソッドでファイルデータを受け取ってファイル保存

@app.get("/download_from_df")
def download_from_df(ext: str) -> StreamingResponse:
    """DataFrameを指定ファイル形式でダウンロードするAPI
       (ローカルにファイル保存せず、データをファイル化して返す)
    """
    if ext == "csv":
        stream = io.StringIO()
        sample_df.to_csv(stream, encoding='utf-8', index=False)
        stream.seek(0)
    elif ext == "xlsx":
        stream = io.BytesIO()
        sample_df.to_excel(stream, index=False)
        stream.seek(0)
    else:
        raise HTTPException(status_code=400, detail="Illegal extension.")
        
    filename = f"sample.{ext}"
    media_type = f"file/{ext}"
    
    return StreamingResponse(
        content=stream, 
        media_type=media_type,
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )
# ファイルで取得
res = requests.get(API_URL+"/download_from_df?ext=csv")

ファイルデータのresponseの場合の書き方です。ブラウザで普通にURLにアクセスしたときはファイルダウンロードが始まりますが、Pythonのrequestsモジュールの場合はバイナリデータで受け取る形になります。中身はres.contentで取得できます。
出力は以下。

b'first_name,last_name,age,part\r\nHiroji,Miyamoto,58,Vo./Gt.\r\nToshiyuki,Ishimori,57,Gt.\r\nSeiji,Takamidori,58,Ba.\r\nYoshiyuki,Tominaga,58,Dr.\r\n'  

ファイルを出力したい場合はwith open()からバイナリ書き出しモードを指定することで可能です。
下記のサイトが参考になりますので併せてご確認ください。
Pythonでファイルをダウンロードする #言語処理100本ノック - Qiita