http.serverをchromeが独占する問題と解決策
[質問]
Pythonのhttp.serverで立てたローカルWebサーバーにchromeとfirefoxでアクセスしたところ、何かのタイミングでchromeがHTTP接続を握ったままになり、セッション数の制限から、firefoxで接続できなくなります。解決策はありますか。
[回答] Grok
はい、これは Pythonの組み込みhttp.server(旧SimpleHTTPServer) を使っているときによく起こる、かなり有名な問題です。
主な原因は以下の組み合わせです:
http.serverはシングルスレッドで動く(socketserver.TCPServerベース)- HTTP/1.1のpersistent connection(Keep-Alive)をデフォルトで許可している
- Chromeが非常に積極的にKeep-Alive接続を使い続け、かつ並列リクエストを複数発行しようとする
- 一つの接続が「読み込み待ち」の状態で開いたままになると、サーバーが新しい接続を受け付けられなくなる
結果として、Chromeが1本の接続を握り続けたままにすると、他のブラウザ(Firefoxなど)が接続できなくなる、という症状が出ます。
現実的な解決策(おすすめ順)
| 順位 | 方法 | 難易度 | おすすめ度 | 備考 |
|---|---|---|---|---|
| 1 | ThreadingMixIn を使う | ★★☆ | ★★★★★ | 一番おすすめ |
| 2 | --bind 127.0.0.1 を明示 | ★☆☆ | ★★★★☆ | 簡単だが効果は中程度 |
| 3 | Chromeの「プリフェッチ/予測サービス」をオフ | ★☆☆ | ★★★☆☆ | 根本解決ではない |
| 4 | HTTP/1.0強制(protocol_version変更) | ★★☆ | ★★☆☆☆ | Keep-Aliveを切るが非推奨 |
| 5 | http.server ではなく他のサーバーを使う | ★★★★ | ★★★★★ | 長期的にベスト |
1. 最もおすすめ:ThreadingMixIn を使う(同時接続対応)
import http.server
import socketserver
PORT = 8000
# ここがポイント
class ThreadedHTTPServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
"""Handle requests in a separate thread."""
pass
# ハンドラはそのまま
Handler = http.server.SimpleHTTPRequestHandler
# ThreadedHTTPServer を使う
with ThreadedHTTPServer(("", PORT), Handler) as httpd:
print(f"serving at port {PORT}")
httpd.serve_forever()
これだけで同時接続を複数処理できるようになり、Chromeが接続を握っていてもFirefoxが普通に繋がるようになります。
2. とりあえず試す価値あり(超簡単)
--bind 127.0.0.1 を付けると、Chromeの妙な挙動が多少マシになるケースが結構あります。
3. Chrome側の設定変更(一時しのぎ)
Chromeで
chrome://settings/privacy → 「ページのプリロード」または「予測サービスを利用してページをより速く読み込む」のチェックを外す
かなり古い問題ですが、いまだに効く環境が残っています。
まとめ(2026年現在でも有効な現実解)
一番手っ取り早く、かつ根本的に解決したいなら
ThreadingMixInを使ったサーバーを自分で書くのが最もおすすめです。
# 最小構成・おすすめ版
import http.server
import socketserver
PORT = 8000
class ThreadingSimpleServer(socketserver.ThreadingMixIn,
http.server.HTTPServer):
pass
with ThreadingSimpleServer(("", PORT),
http.server.SimpleHTTPRequestHandler) as httpd:
print(f"http://localhost:{PORT}")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nシャットダウンします")
httpd.server_close()
これでほぼ100%解決します。
必要なら--cgiも使えるようにCGIHTTPRequestHandlerに変えたりできます。
お試しください!