OneDriveの中にPythonの仮想環境(venv)を置くと、自動実行で壊れることがある
Pythonのスクリプトを手で動かして、うまくいくことを確かめた。それをタスクスケジューラに登録して、毎晩自動で動くようにした。ところが翌朝ログを見ると、ModuleNotFoundError で止まっていた。手で動かしたときは、確かに動いていたのに。
これは私が実際にはまった例です。原因は、Pythonの仮想環境(venv)をOneDriveの同期フォルダの中に作っていたことでした。この記事では、何が起きたかと、直し方をまとめます。
何が起きたか
状況は次のとおりでした。
- プロジェクトのフォルダはOneDriveの中にあり、venvもその中に作った
pip install -r requirements.txtで必要なライブラリを入れ、手で動かして成功を確かめた- その日のうちに、毎晩動くようタスクスケジューラに登録した
翌朝、ログには No module named 'playwright' というエラーが並んでいました。失敗したら再試行する設定にしていましたが、7回の再試行もすべて同じエラーです。venvの中身を見ると、ライブラリを入れる site-packages フォルダから、pip以外のライブラリがほとんど消えていました。
原因の見立て
はっきりした原因までは突き止められていません。ただ、状況から考えると、venvを作った直後に、OneDriveが大量の小さなファイルを同期している途中で何かが競合し、ファイルが消えたのだと考えています。ライブラリを入れたvenvは、数千のファイルを含むことも珍しくありません。
いずれにしても、venvをOneDriveに置く理由はほとんどありません。Pythonの公式ドキュメントでは、仮想環境は「移動やコピーをするものではなく、使う場所で作り直すもの」と説明されています。別のパソコンに同期しても、そのままでは使えないのです。同期する意味が無く、壊れたときに気づきにくいものを、同期フォルダに置いておく必要はありません。
気づかないうちにOneDriveの中にいることがある
「OneDriveに置いたつもりはない」という人も、一度確かめてみてください。WindowsのOneDriveには、デスクトップやドキュメントといったおなじみのフォルダをOneDriveへ移す(リダイレクトする)機能があります。Microsoftの説明では、対象はデスクトップ、ドキュメント、ピクチャ、スクリーンショット、カメラロールです。この機能を有効にしていると、「ドキュメント」の中に作ったプロジェクトは、実際にはOneDriveの同期フォルダの中にあります。
確かめるには、プロジェクトのフォルダでPowerShellを開き、次のコマンドを実行します。表示されたパスに OneDrive が含まれていれば、同期の対象です。
(Get-Location).Path
直し方: venvだけをOneDriveの外に作る
スクリプト本体まで動かす必要はありません。OneDriveの外に移すのは、venvだけです。
| もの | 置き場所 | 理由 |
|---|---|---|
| スクリプト本体(.py、.bat など) | OneDriveの中のままでよい | 小さなファイルが少しだけで、バックアップされる利点がある |
| requirements.txt | OneDriveの中のままでよい | venvを作り直すときの材料になる |
| venv(仮想環境) | OneDriveの外に移す | ファイルが多く、同期する意味が無い。壊れても気づきにくい |
私は、ユーザーのフォルダの下に .venvs というフォルダを作り、プロジェクトごとにvenvを並べています。PowerShellで次のように作ります(myproject はプロジェクトの名前に置き換えてください)。
python -m venv "$env:USERPROFILE\.venvs\myproject"
& "$env:USERPROFILE\.venvs\myproject\Scripts\python.exe" -m pip install -r requirements.txt
作り直したら、OneDriveの中にある古いvenvのフォルダは消して構いません。Pythonの公式ドキュメントでも、場所を変えたいときは新しい場所で作り直し、古いほうを消すよう書かれています。
activateしないで、python.exeを直接呼ぶ
venvを使うとき、Activate.ps1 を実行して「有効化」する手順がよく紹介されます。しかしWindowsの既定の実行ポリシー(Restricted)では、スクリプトの実行が許可されていないため、Activate.ps1 はエラーで止まります。
実は、有効化はしなくても構いません。Pythonの公式ドキュメントにも、仮想環境のPythonをフルパスで指定して実行すれば、有効化は必ずしも要らないと書かれています。タスクスケジューラから呼ぶバッチファイルでは、次のようにvenvの python.exe を直接指定します。
run.bat(タスクスケジューラから呼ぶ)
@echo off
"%USERPROFILE%\.venvs\myproject\Scripts\python.exe" "%~dp0main.py"
exit /b %ERRORLEVEL%
%~dp0 は、このバッチファイルがあるフォルダを表します。スクリプト本体はOneDriveの中、venvは外、という分け方のまま動かせます。最後の行は、Pythonが失敗したときにタスクも失敗として記録されるよう、終了コードを返すためのものです。
作り直しの手順
- 1. 外に作る%USERPROFILE%\.venvs\ の下に新しいvenvを作る
- 2. 入れ直すrequirements.txt から必要なライブラリを入れる
- 3. 呼び先を変えるバッチファイルの python.exe のパスを新しいvenvに
- 4. 古いのを消すOneDriveの中の古いvenvを削除する
手で動かすvenvまで移す必要はない
私は、毎日の自動実行に使うvenvだけを移しました。手でたまに動かすだけのプロジェクトなら、もし壊れてもその場で気づけて、作り直せば済みます。問題になるのは、無人で動いていて、壊れても誰も気づかないvenvです。自動実行を組むときに、そのvenvの置き場所だけ確かめておけば十分です。
まとめ
- OneDriveの同期フォルダに置いたvenvの中身が消え、自動実行が
ModuleNotFoundErrorで止まったことがある - venvは移動やコピーをするものではないので、同期する意味が無い。OneDriveの外(例:
%USERPROFILE%\.venvs\)に作る - デスクトップやドキュメントは、OneDriveに移されていることがある。パスに
OneDriveが含まれていないか確かめる Activate.ps1は使わず、venvのpython.exeをフルパスで呼ぶ
Claude Codeを毎日自動で動かす方法は、WindowsのタスクスケジューラでClaude Codeを毎日自動で動かすにまとめています。