仮想環境を利用していて発生した問題についてまとめました。
過去に誤った操作をしたことに気づかなかったことでエラーの究明に時間がかかかったので記事にまとめました。
このような愚行をしている同種の人々はいなさそうで他に記事がなさそうだったため、備忘録と誰かの参考になれば幸いです。
概要
仮想環境について詳しくないため、不正確な情報があるかもしれません。
| OS | 言語 | 仮想環境 |
|---|---|---|
| ubuntu | python3 | venv |
下記のコマンドをprojectBというディレクトリで実行。
$ pwd
# 出力結果
# home/user/projectB
$ source .venv/bin/activate
echo $VIRTUAL_ENV
# 出力結果
# /home/user/projectA/.venv
#本来はこっち
# /home/user/projectB/.venv
現在、projectBのディレクトリにいるがprojectAの仮想環境が利用されている。
アクティベートしたはずの仮想環境とは異なる仮想環境が利用されていた。
原因はprojectBの仮想環境の設定に由来していた。
対応策は、.venvの仮想環境を削除し再構築することで期待通りの動作になる。
異なる仮想環境が利用されていた原因
状況
いつも通りのコーディングをprojectAのディレクトリで行っていた。
よく考えもせずにディレクトリを作成したりファイルを配置したりでパスの管理が面倒になり始めるのである。
ついでの勢いでGit管理やディレクトリ構造などを刷新するためにprojectBというディレクトリを作成した。
projectAはバックアップとして保持しておきたいため、cpコマンドでprojectAの中身をprojectBにコピーした。
これが、変な挙動の生み出してしまう元凶たる行為であった。
原因
結論から述べると、コピーしていた仮想環境をそのまま利用していたことが原因であった。もう少し説明を加えると、アクティベートする.venvの仮想環境のパスが変更されていないことに由来するものだった。
具体的な箇所
cat -n .venv/bin/activate
cat -n [filename]で行数を含めて表示する。
41 VIRTUAL_ENV=/home/user/projectA/.venv
42 export VIRTUAL_ENV
ここです。
作成した仮想環境のディレクトリの中にあるactivateというファイルがある。ここのVIRTUAL_ENVのパスがprojectBではなくprojectAになっていた。それはそう。projectAの時に作成したため、その時のパスのままの設定で仮想環境が利用されている。
projectBにも仮想環境はあるが、パス指定されているためprojectAの仮想環境が利用されていたということである。
projectBの仮想環境を使いたいなら.venv/bin/activateのVIRTUAL_ENVを書き直せば動くと思われる(そもそも仮想環境をコピーするな)。
VIRTUAL_ENVを書き直せば動作しそうではあるが、仮想環境には他にも様々なファイルがあるため、削除してから再構築する方が安全で確実である。
なぜ発覚したのか
from pydantic_settings import BaseSettings, SettingsConfigDict
pip installしたはずのモジュールがインポートできない。
もちろん仮想環境(venv)をアクティベートしてからpip installを行った。
さらには、pip listで確認するとモジュールがインストールされていた。
加えて、実行時にはなぜかエラーを吐かずに正常に動作する。
もはや意味不明だった。
コードの実行に関しては特段、問題がなかったためインタープリタのエラーは無視することもできた。
ただ、コード開発の利便性や何か異常が起きていることは目に見えている。
この問題を解消するために色々試した結果、前述した原因が分かり解決策も判明した。
おわり
こんな不可解な現象は異なる仮想環境を利用していたという一つの原因から発生している。
モジュール関連はソースコードがあるディレクトリの仮想環境を利用しているため、インタープリタがエラーを出す。
ただ、実行に関してはパスで指定されていた仮想環境が使われるためなんの異常な処理は起きない。
端的に述べると、コーディング時と実行時に参照する仮想環境異なり不整合な動作が生まれていた。
