Python|requestsの通信設計ミスを防ぐ実践整理法
この記事のポイント
- 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()
@Reviewertimeout未指定により無限待機リスクがあります。タイムアウト設計を必須化してください。
問題点
- 相手側応答不在時に無限待機化
- リソース消費・障害拡大
崩壊構造モデル:タイムアウト不備構造
requests設計整理の原則
以下の通信設計整理文化が健全性維持に有効です。
① タイムアウト強制文化
- timeout明示必須(接続/読み込み分離可)
② 例外粒度整理文化
- requests.exceptions各種を整理捕捉
③ リトライ責務整理文化
- 一時的障害への再試行文化導入
④ 通信層抽象化文化
- 通信ロジックは業務ロジックから分離
⑤ 監視通知文化
- 異常検知は監視系統へ連携設計
改善例:タイムアウト整理版
タイムアウト整理版
import requests
response = requests.get(
"https://api.example.com/data",
timeout=(5, 10) # 接続5秒、読み込み10秒
)
data = response.json()「timeout文化+責務分離文化」
レビューアーは「timeout指定強制文化」を徹底確認すると設計臭抑止できます。
改善構造モデル:タイムアウト整理
良くない実装例: ケース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文化・リトライ文化・通信責務文化」を育成指導することで、
障害耐性と保守性の高い通信設計を安定化できます。

