やったこと
ディレクトリを経由することでcondaの環境を自動で切り替えられるようにしました。
自動切換したいディレクトリ直下の.env
ファイルにCONDA_ENV="hogehoge"
を追記する形で環境を指定することで、ディレクトリに入ると自動で環境を切り替えてくれます。
中身
まず、前提としてcondaをインストールした後、condaのbase環境が自動的にactivateされる機能を切ります。
conda config --set auto_activate_base false
以下を~/.profile
なり~/.bashrc
なりの設定ファイルに追記します。
function conda_auto_env() {
LAST_COMMAND=$(history 1 | sed 's/^[ ]*[0-9]*[ ]*//')
if [[ -e ".env" && $LAST_COMMAND != "conda"* ]]; then
source .env
if [[ -n "$CONDA_ENV" && $CONDA_DEFAULT_ENV != "$CONDA_ENV" ]]; then
if conda activate "$CONDA_ENV" &>/dev/null; then
export CONDA_ACTIVATED_DIR="$PWD"
export CONDA_ACTIVATED_ENV="$CONDA_ENV"
else
echo "Failed to activate conda environment: $CONDA_ENV"
fi
fi
elif [[ -n "$CONDA_ACTIVATED_DIR" && "$PWD" != "$CONDA_ACTIVATED_DIR"* ]]; then
if [[ -n "$CONDA_ACTIVATED_ENV" && $CONDA_DEFAULT_ENV == "$CONDA_ACTIVATED_ENV" ]]; then
conda deactivate &>/dev/null
fi
export CONDA_ACTIVATED_DIR=""
export CONDA_ACTIVATED_ENV=""
fi
}
export PROMPT_COMMAND="conda_auto_env;$PROMPT_COMMAND"
自動アクティベートをしたいときは、対象のディレクトリ以下、たとえは/example/hoge/fuga
以下に.env
ファイルを作成し、以下のように書き込みます。
CONDA_ENV="hogehoge"
この状態で、cd /example/hoge/fuga
すると自動的にactivateが走りhogehoge
環境に入ります。このディレクトリや子孫のディレクトリではdeactivateはせず、子孫を含むディレクトリの外に出ると自動的にdeactivateします。
実装はわりと雑なので、自分なりにカスタマイズする必要があるかもしれません…。
やりたいこと
pyenvでは.pyenv-versionファイルがあるディレクトリ以下に移動した際、自動的にpythonバージョンが切り替わる仕組みになっています。しかし、condaでは環境を使うたびに毎度activateしなければなりません。
同じプロジェクトのディレクトリ内で環境を変えることはほぼないので、できればpyenvのようにディレクトリに移動した段階で、自動的に切り替わってほしいです。
ただ、ディレクトリの内部で環境を変えたいことも、たまーにあるので、そのときに干渉してほしくないという願いもあります。
やってること(コードの中で)
export PROMPT_COMMAND="conda_auto_env;$PROMPT_COMMAND"
まず、最後の行のPROMPT_COMMAND
によってbash等でなにかを実行した後に自動的に呼び出される関数として、conda_auto_env
を登録しておきます。これによって、bashで何かを打ち込むたびに、conda_auto_env
が自動的に呼び出されるようになります。
つぎに、関数の中身です。
LAST_COMMAND=$(history 1 | sed 's/^[ ]*[0-9]*[ ]*//')
if [[ -e ".env" && $LAST_COMMAND != "conda"* ]]; then
source .env
if [[ -n "$CONDA_ENV" && $CONDA_PREFIX != *"$CONDA_ENV"* ]]; then
if conda activate "$CONDA_ENV" &>/dev/null; then
export CONDA_ACTIVATED_DIR="$PWD"
export CONDA_ACTIVATED_ENV="$CONDA_ENV"
else
echo "Failed to activate conda environment: $CONDA_ENV"
fi
fi
ディレクトリ内部に.envファイルが存在する場合は、それを読み込んでCONDA_ENVが定義されているか探します。それが存在し、かつactivateされていないことを$CONDA_DEFAULT_ENV != $CONDA_ENV
によって確かめています。このCONDA_DEFAULT_ENV
はcondaが勝手につくってくれる環境変数で、現時点でアクティベートされているenvの名前が入っています。
アクティベートされていないことが分かったら、こんどはCONDA_ENV
の名前でconda activate
します。もしCONDA_ENVで指定された名前の環境が存在しなかった場合はエラーメッセージを表示し、存在した場合はCONDA_ACTIVATED_DIR
とCONDA_ACTIVATED_ENV
をそれぞれ環境変数としてexportします。
elif [[ -n "$CONDA_ACTIVATED_DIR" && "$PWD" != "$CONDA_ACTIVATED_DIR"* ]]; then
if [[ -n "$CONDA_ACTIVATED_ENV" && $CONDA_DEFAULT_ENV == "$CONDA_ACTIVATED_ENV" ]]; then
conda deactivate &>/dev/null
fi
export CONDA_ACTIVATED_DIR=""
export CONDA_ACTIVATED_ENV=""
fi
}
つぎに、.env
ファイルが存在しない場合、まず現在のディレクトリと自動アクティベート時にexportしたCONDA_ACTIVATED_DIR
を比較し、もしCONDA_ACTIVATED_DIR
以下にいなかった場合はdeactivateを試みます。なお、この際ユーザーによって自動でactivateした環境と異なる環境が読み込まれていた場合はdeactivateを行いません。
このほかにも、この関数が呼び出される直前に行った操作(ユーザーが打ったコマンド)を取得して、condaそれがconda関係の場合は処理を行わないなどしています。負荷軽減のため、cd
以外で呼び出さないとかにしてもいいかもしれません。あと、使うファイルが.env
なのも人によって嫌悪感があると思いますので、人によって書き換えたほうがいいと思います。個人的にはgitなどで共有することのないファイルがお勧めです。環境名は人によって違うので。
まとめ
ぱっと調べた感じ、condaの自動activateがなかったので作ったのですが、実はあったりするんですかね…。ChatGPTに聞いた感じだとdirenvとかでできるっぽいんですが、いうて管理したいのがcondaくらいだったので簡単にこういった形で実装してみました。っていうか、そもそもないのがおかしくないですかね…。
基本的にはpipとかを利用しているのですが、たまーにcondaが欲しくなったりして、そうすると後々普通にpyenvでpythonを入れたことを後悔しがちです。condaであれば、この環境変更の煩わしさを抜ければ、pipを使う場合は環境だけ作ってconda使わなければいいですし、使いたいときはcondaも使えるので良いかもしれません。特に、condaは昔のバージョンのTorchとかを入れるときにわりと便利(最近のバージョンではpipでもcuda勝手にインストールしてくれる)ですね。
参考