Playwrightで「Executable doesn't exist」になる原因と直し方(別のvenvが共有のブラウザを消すことがある)
毎日自動で動かしていたPythonのPlaywrightスクリプトが、ある日突然、ブラウザを起動できずに止まった。コードは何も変えていない。前日までは動いていた。
これは私が実際にはまった例です。原因は、ブラウザ本体が複数のプロジェクトで共有されていて、別のプロジェクトの操作で消されたことでした。この記事では、何が起きたかと、直し方、再発の防ぎ方をまとめます。
どんなエラーになったか
私の環境のログには、次のような形のエラーが出ていました(パスは置き換えています)。
BrowserType.launch: Executable doesn't exist at
C:\path\to\ms-playwright\chromium_headless_shell-XXXX\...\headless_shell.exe
メッセージには「Playwrightをインストールまたは更新した直後のようです」という趣旨の案内も付いていました。ただ、私のケースでは、そのプロジェクト自体は何も更新していませんでした。真因は、別のプロジェクトがブラウザを消したことです。この案内に引きずられないほうがよいと感じました。なお、このエラー文の形は私の環境のログで見たもので、公式ドキュメントには載っていません。Playwrightの版によって番号や文言は違うはずです。
原因: ブラウザはvenvの外の共有フォルダにある
PlaywrightのPython版は、pip install playwright でライブラリを入れたあと、playwright install でブラウザ本体を別に入れます。公式ドキュメントによると、ブラウザの保存場所は、Windowsでは %USERPROFILE%\AppData\Local\ms-playwright です。venvの中ではないので、同じユーザーの全プロジェクトで共有されます。
さらに、公式ドキュメントには次の説明があります。
- Playwrightの版ごとに、必要なブラウザの版が決まっている("Each version of Playwright needs specific versions of browser binaries to operate.")
- Playwrightはブラウザを使っているクライアントを記録していて、ある版のブラウザを必要とするクライアントがいなくなると、その版は削除される("When there are no more clients that require a particular version of the browser, that version is deleted from the system.")
つまり、プロジェクトAがPlaywrightの古い版を使い、プロジェクトBが新しい版を使っているとき、Bで playwright install を実行すると、Aが必要とする古い版のブラウザが「誰も使っていない」と判断されて消されることがあります。私の環境では、Aは pip install しただけで playwright install を実行していませんでした。そのため、Aがブラウザの利用者として記録されておらず、消される側に回ったのだと考えています。
起きたこと
- 1. 共有の場所ブラウザはvenvの外の ms-playwright に置かれ、全プロジェクトで共有
- 2. 別の更新プロジェクトBで新しい版を入れ、playwright install を実行
- 3. 掃除される使う利用者がいない古い版のブラウザが削除される
- 4. Aが止まる翌日の自動実行で Executable doesn't exist
直し方
止まったプロジェクトのvenvで、そのvenvのPythonからブラウザを入れ直します。
"C:\path\to\venv\Scripts\python.exe" -m playwright install chromium
venvを有効化しなくても、python.exe をフルパスで呼べば、そのvenvのPlaywrightの版に合ったブラウザが入ります(この方法はvenvをOneDriveの外に置く話でも使っています)。公式ドキュメントによると、Playwrightにはヘッドレス用の別ビルド(chromium headless shell)があり、playwright install chromium でChromiumが入ります。
私の環境では、他のプロジェクトと同じ版のPlaywrightに揃えてから入れたところ、すでにあるブラウザが再利用され、ダウンロードは発生しませんでした。
再発を防ぐ
| 方法 | 内容 | 向いている場面 |
|---|---|---|
| venvを作ったら必ずinstallまで | pip install のあとに python -m playwright install chromium まで実行する | まず全員がやること。私はこれで止まらなくなった |
| 置き場所を分ける | 環境変数 PLAYWRIGHT_BROWSERS_PATH で、インストール時と実行時に同じ場所を指定する | プロジェクトごとにブラウザを独立させたいとき |
| 自動削除を止める | PLAYWRIGHT_SKIP_BROWSER_GC=1 を設定するか、installに --no-remove を付ける | 古い版を意図的に残したいとき |
| 入っているEdge・Chromeを使う | 起動時に channel="msedge" や channel="chrome" を指定する | Playwright用のブラウザを入れたくないとき |
PLAYWRIGHT_BROWSERS_PATH は、公式ドキュメントに、ブラウザを特定の場所へ入れさせることと、実行時にその場所を探させることの両方に使えると書かれています。分ける場合は、インストールと実行の両方で同じ値を指定してください。
channel は、Python版では次のように指定します。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(channel="msedge")
公式ドキュメントによると、channel には "chrome"、"msedge" などが指定できます。ただし、既定は同梱のChromiumで、公式ドキュメントでは、多くの場合は既定の設定(最新のChromium)を使うのがよいと説明されています。入っているEdgeやChromeが自動更新されて挙動が変わる可能性は、頭に入れておいてください。
無人実行で早く気づくために
手で動かしているときは、エラーはその場で見えます。毎日の自動実行で怖いのは、失敗に気づかず何日も止まることです。タスクスケジューラの終了コードを記録する、成功の印のファイルを毎回更新して古くなったら通知する、といった仕組みを足しておくと、止まった翌日には気づけます。考え方はタスクスケジューラの失敗に気づく方法 ― 自動実行を毎朝一覧で確かめるでまとめています。また、タスクの組み方はWindowsのタスクスケジューラでClaude Codeを毎日自動で動かすに書いています。
まとめ
- Playwrightのブラウザはvenvの外の共有フォルダにあり、Playwrightの版ごとに必要な版が違う
- 使うクライアントがいなくなった版は削除される。別のvenvの操作で、動いていたプロジェクトのブラウザが消えることがある
- 直すには、そのvenvのPythonで
-m playwright install chromiumを実行する - venvを作ったら、
pip installだけで終わらせず、必ずinstallまで実行する - 置き場所を分ける、自動削除を止める、入っているEdge・Chromeを使う、という選択肢もある