ブラウザ自動化処理を Playwright で動かしていたら、ある日から軒並み NotImplementedError で落ちるようになった。しかも厄介なことに、コードを直して保存しても挙動が変わらない。/health が返す git_sha が古いまま固着していた。半日溶かしたので、症状から原因までを残しておく。
環境
- Windows
- Python / uvicorn 0.41
- Playwright(chromium, async API)
- 開発時は
uvicorn app:app --reloadで起動
何が起きたか
- Playwright で chromium を起動する処理が、すべて
NotImplementedErrorで落ちる - そのくせ
str(e)が空で、ログには「実行エラー: 」としか出ない(原因がまったく見えない) - さらに、コードを直しても反映されない。
/healthの git_sha が古いコミットのまま固まっている
この2つが同時に出たので「別々の不具合」だと思い込んで、しばらく別方向を掘っていた。実際は根が1つだった。
原因
Windows で uvicorn に --reload を付けると、内部で use_subprocess=True になり、worker が SelectorEventLoop に載る。
SelectorEventLoop は サブプロセス生成に非対応で、asyncio のサブプロセス API を呼ぶと NotImplementedError を投げる。Playwright は chromium を別プロセスで起動するので、ここで全滅していた。
そして「直しても反映されない」の正体も同じ --reload だった。リロード用の監視プロセスがうまく回らず、リロードが完走しないまま古いワーカーが居座っていた。エラーの見えなさ(空の NotImplementedError)と相まって、原因特定に時間を取られた。
根治
-
--reloadを撤去し、ProactorEventLoop(Windows のデフォルト側)で常駐させる - コードの反映は「自動リロード頼み」をやめて、明示的な再起動に切り替える
これで Playwright は正常に chromium を起動できるようになり、反映固着も消えた。
一般化
「直しても反映されない」+「サブプロセスが全部落ちる」が 同時に出たら、まず開発サーバーの --reload を疑う。プラットフォーム(ここでは Windows)とイベントループの組み合わせが、フレームワークの便利機能と噛み合っていないケースだった。
こういう「入門記事には載っていない詰まり」を、実際にハマって直した事例だけ集めて、症状 → 原因 → 根治で逆引きできるようにまとめている(無料で数本読める)。