ys memos

Blog

pyenvをauto activate


python

2021/06/16


Python パッケージをそのままの pip ですべてインストールして使っていると,パッケージリストが肥大化したり,バージョン指定があるパッケージを使用する際などにいちいちインストールしなければならなくなり,不便なことがある.

そんな人にとって重宝するのが,virtualenvpyenvanacondaであろう.

これらを使うと,プロジェクトごとにライブラリを管理できるため,pip freezeなどもラクラクである.

しかし,これらをそのまま使おうとすると,プロジェクトを切り替える毎に環境をアクティベートするのが面倒であった.

特に,ディレクトリベース(anaconda以外)の方を使うと,隠しファイルにして環境情報を格納するので,どこにアクティベートするスクリプトが負いてあるのか探すのが自分にとって大変だった.


他にもよい扱い方があるかもしれないが,私の場合は以下を考えた.

環境情報を格納するファイルを.venvという名前で決め,カレントディレクトリが.venvに管理されたディレクトリかどうかを自動で探せばいいじゃんと思った.


Python スクリプトに限らずだが,ファイルをネストして配置することも多いので,.venvの適用範囲は,カレントディレクトリはもちろんのこと,子ディレクトリ,孫ディレクトリ,曽孫ディレクトリ(?)...までずっと広げたい.

つまり,再帰して.venvを探せばよい.

また,.venv/などに配置することは(私の場合は)ありえないので,探索範囲を/home/<username>までと決めてしまった.


こんな感じ

.bashrc
_auto_activate_nested_venv() {
  if [[ ${PWD} != *${HOME}* ]]; then
    return
  fi

  env_key='.venv'
  search_path=$PWD
  while [ ${search_path} != ${HOME} ]
  do
    if [ -e "${search_path}/${env_key}" ]; then
      env_dir=${search_path##*/}

      if [ ${_VENV_NAME} ] && [ ${env_dir} == ${_VENV_NAME} ]; then
        break;
      fi

      if [ "$VIRTUAL_ENV" != "${search_path}/${env_key}" ]; then
        env_owner=$(stat -c '%U' ${search_path}/${env_key})
        if [ $env_owner != $USER ]; then
          echo '[VENV OWNER]: '$env_owner

          # For security: question if `.env` is third party
          read -p "Do you activate? [y/N]" -n 1 -r
          if [[ ! $REPLY =~ ^[yN]$ ]]; then
            return
          fi

        else
          echo '[ENV OWNER]: '$env_owner
        fi

        _VENV_NAME=$(basename ${search_path##*/})
        echo Activating virtualenv \"$_VENV_NAME\"...
        VIRTUAL_ENV_DISABLE_PROMPT=1
        source ${search_path}/${env_key}/bin/activate
        _OLD_VIRTUAL_PS1="$PS1"
        PS1="(pyenv $_VENV_NAME)$PS1"
        export PS1
      fi
      break
    fi
    search_path=${search_path%/*}
  done

  if [ ${_VENV_NAME} ] && [ ${HOME} == ${search_path} ]; then
    _VENV_NAME=''
    deactivate
  fi
}
export PROMPT_COMMAND=_auto_activate_nested_venv # この書き方だと上書きするので,すでに他に設定している場合は,既存を含めるようにexportする

だいぶ便利になった


(過去に作った設定なので,参考元を忘れてしまいました...すみません)

関連タグを探す