httpxはrequestsをどう進化させたか
🧭 はじめに(What / Why)
このページでは、HTTPX が requestsをどう進化させたのかを理解します。
- requestsの「成功した前提」を壊さずに、何を追加したのか
- sync/async 両対応が「便利」以上に何を意味するのか
- HTTP/2対応やタイムアウト設計が、実運用で何を変えるのか
到達点はこれです。 「httpxは“requestsの書き味”を保ったまま、現代のI/O要件(async・HTTP/2・堅いデフォルト)に適応した」。
🕰 立ち位置の整理(Before / After)
Before: requestsの強さと限界
requestsは「人間向けHTTP API」を完成させ、同期HTTPの事実上の標準になりました(ただし、設計としては同期が中心)。 一方で、現代のWeb/サービス運用では次が要求されがちです。
- 非同期I/O(asyncio等)と自然に繋がること
- 多数同時接続や長時間接続を前提にした効率
- “止まらない”を避ける、デフォルトの堅牢性(timeouts等)
After: httpxの狙い
httpxは 「requestsの書き味」 を維持しつつ、次を提供します。
- sync/async 両方のAPI (python-httpx.org)
- HTTP/1.1 と HTTP/2 の両対応 (python-httpx.org)
- デフォルトでタイムアウトを強制(“永遠に待つ”を避ける) (python-httpx.org)
🧠 設計思想の核(最重要)
1) 「同じモデルを sync/async に持ち込む」
httpxは、同期と非同期を「別物のライブラリ」に分裂させず、同じ設計モデルで提供します。 公式ドキュメントでも、通常は同期APIを使い、必要ならAsyncClientを選べる、という立て付けです。 (python-httpx.org)
「同期から非同期へ」の移行で最もコストが高いのは、コード量よりも考え方・道具立ての差です。httpxはその摩擦を減らす設計です。
2) HTTP/2対応は「速い」より「接続を賢く使う」
HTTP/2はリクエスト/レスポンスの意味は変えず、データの運び方(多重化など)を改善するプロトコルです。 (python-httpx.org) httpxがHTTP/2をサポートするのは、「一発が速い」よりも 並行処理・接続効率の文脈で効くことが多い(=asyncと相性が良い)という思想に繋がります。 (GitHub)
3) “安全側のデフォルト” を標準搭載する
httpxは デフォルトでタイムアウトを徹底し、ネットワーク無応答が続けば例外にします(5秒が基準)。 (python-httpx.org) これは「毎回timeoutを書くべき」議論を、設計で解消する方向です。
requestsから移行すると「timeout指定を忘れても動く」感覚のまま運用に入ってしまいがちだが、httpxは運用の現実(ハング・枯渇・詰まり)を前提にしている。
4) “拡張できる内部構造” を前面に出す
httpxはTransport層を公開し、Request/Responseモデルを保ったまま低レイヤを差し替えられる設計を持ちます。 (python-httpx.org)
さらに、依存関係として httpcore(下位トランスポート実装)などを明示しており、層構造を意識した設計です。 (python-httpx.org)
⚖️ できること / できないこと
できること(得意領域)
- requestsに近い書き味での同期HTTP (python-httpx.org)
- asyncio環境での非同期HTTP(AsyncClient) (python-httpx.org)
- HTTP/2利用(オプションで有効化) (python-httpx.org)
- タイムアウト・接続プールなど「運用の基本」をデフォルトで意識 (python-httpx.org)
できないこと / 向いていないこと(境界線)
- 「非同期が必要か不明だが、とりあえずasyncで全部」 → asyncはアプリ全体の設計(呼び出し階層・例外・テスト)に波及する。httpx自体は解決しない。 (python-httpx.org)
- 「HTTP/2だから常に速くなるはず」 → HTTP/2は“運搬効率”の改善で、効果は状況依存。 (python-httpx.org)
同期コードの一部だけをAsyncClientで呼ぶ(イベントループを場当たり的に回す等)は設計事故になりやすい。asyncは「局所導入」しにくい。
🧪 典型的な利用パターン(最小)
同期(requests的な使い方)
import httpx
r = httpx.get("https://api.example.com/items", params={"limit": 10})
r.raise_for_status()
data = r.json()
非同期(asyncio環境)
import httpx
async with httpx.AsyncClient() as client:
r = await client.get("https://api.example.com/items")
非同期APIの提供は、httpxの中核価値のひとつです。 (python-httpx.org)
🚧 よくある誤解・アンチパターン
誤解①: 「requests互換だから移行は置換で終わる」
- “APIが似ている”のは入口の話
- 本当の差分は I/Oモデル(同期/非同期) と 運用設計(timeouts等) (python-httpx.org)
誤解②: 「timeoutは指定しないのが普通」
httpxはデフォルトでタイムアウトを強制し、5秒のネットワーク無活動で例外にします。 (python-httpx.org) 「指定しない=無限待ち」という発想を前提にしていません。
“デフォルトで安全”は便利だが、障害時に例外が増えるのは正常。例外設計(リトライ・サーキット等)を後回しにしない。
誤解③: 「HTTP/2を使えば自動で高速化」
HTTP/2はセマンティクスを変えず、伝送方式を改善するだけです。 (python-httpx.org) サーバ側対応・接続数・同時リクエスト数など前提が揃わないと効果は限定的です。
🔗 他ライブラリとの関係
- requests: “同期HTTPの完成形(枯れて強い)”
- aiohttp: asyncio密結合で、クライアントだけでなくサーバ機能も持つ(フレームワーク寄り) (docs.aiohttp.org)
- httpx: requestsの書き味 + async + HTTP/2 + 運用寄りデフォルト (python-httpx.org)
選択基準を一言で言うなら:
「requestsで十分」な領域は多いが、async/HTTP/2/堅牢デフォルトが要件なら、httpxが“同じ体験のまま”受け皿になる。
🧾 まとめ(1文で言うと)
httpxは、requestsの「人間向けAPI」を保ったまま、async・HTTP/2・堅牢なデフォルトで現代要件に適応したHTTPクライアントである。