この記事のポイント

  • requestsライブラリ使用時の通信設計整理をレビュー視点で体系理解できる
  • タイムアウト、リトライ設計、例外責任の整理技法を学べる
  • 実務での通信設計文化を体系化できる
  • PlantUMLで依存構造と通信責務を可視化整理できる

そもそもrequestsとは

Pythonのrequestsは「HTTP通信を高レベルで扱う標準的ライブラリ」です。
低レイヤーのurllibと比較して扱いやすさ・拡張性を提供します。

requests基本例

import requests

response = requests.get("https://api.example.com/data")
data = response.json()
  • GET/POST/PUT/DELETE等のHTTPメソッドサポート
  • JSON変換の統合
  • ヘッダ・認証・ストリーム対応など柔軟性

なぜこれをレビューするのか

HTTP通信は「非同期・不安定・揮発性を前提とする責務」です。
レビューアーは以下の整理視点を持つ必要があります。

レビューアー視点

  • タイムアウト制御が適切に設計されているか
  • 例外経路が整理されているか
  • リトライ戦略が適用されているか
  • ヘッダ・認証・共通処理が責務分離されているか
  • ログ・通知経路が整備されているか

開発者視点

  • デフォルトタイムアウト(実質無制限)のまま使用
  • try-exceptを全域化または欠落
  • リトライ導入を後回し
  • 直接通信コードを埋め込み肥大化
  • 例外設計の粒度不明瞭

requests崩壊の典型設計臭

崩壊しやすいパターン
  • timeout指定欠落(デフォルト無制限)
  • 例外捕捉がrequests.exceptions.RequestExceptionのみ
  • リトライ不在(短期障害に脆弱)
  • 通信層が直接業務ロジック層に埋込
  • 失敗時通知・監視経路が不備

崩壊例:タイムアウト欠落型

タイムアウト欠落例

response = requests.get("https://api.example.com/data")
data = response.json()
@Reviewer
timeout未指定により無限待機リスクがあります。タイムアウト設計を必須化してください。

問題点

  • 相手側応答不在時に無限待機化
  • リソース消費・障害拡大

崩壊構造モデル:タイムアウト不備構造

UML Diagram

requests設計整理の原則

以下の通信設計整理文化が健全性維持に有効です。

① タイムアウト強制文化

  • timeout明示必須(接続/読み込み分離可)

② 例外粒度整理文化

  • requests.exceptions各種を整理捕捉

③ リトライ責務整理文化

  • 一時的障害への再試行文化導入

④ 通信層抽象化文化

  • 通信ロジックは業務ロジックから分離

⑤ 監視通知文化

  • 異常検知は監視系統へ連携設計

改善例:タイムアウト整理版

タイムアウト整理版

import requests

response = requests.get(
    "https://api.example.com/data", 
    timeout=(5, 10)  # 接続5秒、読み込み10秒
)
data = response.json()
「timeout文化+責務分離文化」

レビューアーは「timeout指定強制文化」を徹底確認すると設計臭抑止できます。

改善構造モデル:タイムアウト整理

UML Diagram

良くない実装例: ケース1(全域try-except)

try全域例

try:
    response = requests.get("https://api.example.com/data", timeout=5)
    data = response.json()
except Exception as e:
    logger.error(e)
@Reviewer
例外粒度が不明確です。requests.exceptions系統に分解整理してください。

問題点

  • 捕捉粒度不明瞭
  • 原因特定困難

改善例:例外粒度整理

例外整理版

import requests

try:
    response = requests.get("https://api.example.com/data", timeout=5)
    data = response.json()
except requests.exceptions.Timeout:
    logger.error("API Timeout")
except requests.exceptions.ConnectionError:
    logger.error("API Connection Error")
except requests.exceptions.RequestException as e:
    logger.error(f"Unexpected API error: {e}")
  • 原因別捕捉で通知内容が明確化

良くない実装例: ケース2(リトライ不在)

リトライ不在例

response = requests.get("https://api.example.com/data", timeout=5)
data = response.json()
@Reviewer
一時障害に対するリトライ設計が欠落しています。再試行文化を導入してください。

問題点

  • 瞬断脆弱性
  • 再送可能障害が利用者障害に直結

改善例:リトライ設計版

リトライ整理版

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
retries = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
adapter = HTTPAdapter(max_retries=retries)
session.mount("https://", adapter)

response = session.get("https://api.example.com/data", timeout=5)
data = response.json()
  • 短期障害復旧可能性向上
  • バックオフ制御で負荷平準化

良くない実装例: ケース3(通信層埋込型)

通信埋込例

def register_user(user_data):
    requests.post("https://api.example.com/register", json=user_data, timeout=5)
@Reviewer
通信ロジックが業務層に埋め込まれています。通信層抽象化を導入してください。

問題点

  • API仕様変更耐性消失
  • テスト容易性低下

改善例:通信層抽象化版

通信分離版

class ApiClient:
    BASE_URL = "https://api.example.com"

    def register_user(self, user_data):
        return requests.post(
            f"{self.BASE_URL}/register",
            json=user_data,
            timeout=5
        )

api_client = ApiClient()
api_client.register_user(user_data)
  • API呼出責務と業務責務を分離整理

観点チェックリスト

まとめ

requests通信設計は「外部依存リスク設計の縮図」です。
レビューアーは「timeout文化・リトライ文化・通信責務文化」を育成指導することで、
障害耐性と保守性の高い通信設計を安定化できます。