更新日: ・ 自動化ノートの管理人

OneDriveの中にPythonの仮想環境(venv)を置くと、自動実行で壊れることがある

Pythonのスクリプトを手で動かして、うまくいくことを確かめた。それをタスクスケジューラに登録して、毎晩自動で動くようにした。ところが翌朝ログを見ると、ModuleNotFoundError で止まっていた。手で動かしたときは、確かに動いていたのに。

これは私が実際にはまった例です。原因は、Pythonの仮想環境(venv)をOneDriveの同期フォルダの中に作っていたことでした。この記事では、何が起きたかと、直し方をまとめます。

何が起きたか

状況は次のとおりでした。

翌朝、ログには 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.txtOneDriveの中のままでよい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. 1. 外に作る%USERPROFILE%\.venvs\ の下に新しいvenvを作る
  2. 2. 入れ直すrequirements.txt から必要なライブラリを入れる
  3. 3. 呼び先を変えるバッチファイルの python.exe のパスを新しいvenvに
  4. 4. 古いのを消すOneDriveの中の古いvenvを削除する
スクリプト本体と requirements.txt はOneDriveの中のままです。

手で動かすvenvまで移す必要はない

私は、毎日の自動実行に使うvenvだけを移しました。手でたまに動かすだけのプロジェクトなら、もし壊れてもその場で気づけて、作り直せば済みます。問題になるのは、無人で動いていて、壊れても誰も気づかないvenvです。自動実行を組むときに、そのvenvの置き場所だけ確かめておけば十分です。

まとめ

Claude Codeを毎日自動で動かす方法は、WindowsのタスクスケジューラでClaude Codeを毎日自動で動かすにまとめています。