0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自動的にcondaの環境を切り替える

Posted at

やったこと

ディレクトリを経由することで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ファイルを作成し、以下のように書き込みます。

.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_DIRCONDA_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勝手にインストールしてくれる)ですね。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?