web-dev-qa-db-ja.com

ディレクトリにcdするときにvirtualenvを自動的にアクティブにする方法

~/Documentsにはたくさんのプロジェクトがあります。私はほぼ専らPythonで作業するので、これらは基本的にすべてpythonプロジェクトです。たとえば、~/Documents/fooには独自のvirtualenv、~/Documents/foo/venvがあります(これらは常にvenvと呼ばれます) )プロジェクトを切り替えるときはいつでも(1日あたり最大10回)、

deactivate
cd ..
cd foo
source venv/bin/activate

deactivatesource venv/bin/activateを入力するのにうんざりするところまで来ました。 cd ../fooだけを使用してvirtualenv操作を処理する方法を探しています。

  • 私は VirtualEnvWrapper に精通しています。私の知る限り、すべてのvirtualenvを別の場所に移動するように見え、削除するよりも少し複雑になります。 (反対意見は大歓迎です!)

  • シェルスクリプトに慣れていません。これを実現する低メンテナンススクリプトを~/.zshrcに追加することをお勧めできれば、それで十分ですが、いくつかの簡単なグーグルから、そのようなスクリプトは見つかりませんでした。

  • 私はzsh/ oh-my-zsh ユーザーです。 oh-my-zshにはこのプラグインがないようです。この質問に対する最良の答えは、これを行うoh-my-zshプラグインを提供する人です。 (ここでの答えが不十分な場合に私がするかもしれないこと。

18
Alex Lenail

このようなものを.zshrcに入れてください

function cd() {
  if [[ -d ./venv ]] ; then
    deactivate
  fi

  builtin cd $1

  if [[ -d ./venv ]] ; then
    . ./venv/bin/activate
  fi
}

Edit:コメントに記載されているように、現在の仮想環境のサブフォルダーにcd- ingすると、非アクティブ化されます。 1つのアイデアは、次のようにcd- ingを新しいものに変更する場合にのみ、現在の環境を非アクティブにすることです。

function cd() {
  builtin cd $1

  if [[ -n "$VIRTUAL_ENV" && -d ./venv ]] ; then
    deactivate
    . ./venv/bin/activate
  fi
}

それはまだ改善される可能性があり、おそらくそれを「プロンプトコマンド」またはフォルダ名の プレフィックスの一致を試みる に変えて、パスのどこかに仮想環境があることを確認しますが、私のShell-fuは良くありません足りる。

7
agnul

.bashrcまたは.zshrcに以下を追加します

function cd() {
  builtin cd "$@"

  if [[ -z "$VIRTUAL_ENV" ]] ; then
    ## If env folder is found then activate the vitualenv
      if [[ -d ./.env ]] ; then
        source ./.env/bin/activate
      fi
  else
    ## check the current folder belong to earlier VIRTUAL_ENV folder
    # if yes then do nothing
    # else deactivate
      parentdir="$(dirname "$VIRTUAL_ENV")"
      if [[ "$PWD"/ != "$parentdir"/* ]] ; then
        deactivate
      fi
  fi
}

このコードは、誰かがサブフォルダーに入っても、virtualenvを非アクティブ化しません。 @ agnul および @ Gilles の回答に触発されました。

Virtualenvがpipenvで作成されている場合は、 このWikiページ を検討してください。

さらに、セキュリティを強化するために direnv を検討してください。

14
MS_

カスタムスクリプトを作成する代わりに、 direnv を使用できます。これはzsh固有のソリューションではありません(そのため zsh-autoenv を試すことができます)が、十分に保守されており、zshで簡単に使用できます。インストールしたら、_.zshrc_の最後にeval "$(direnv hook zsh)"を挿入します。その時点で、次のことができます。

_$ source ~/.zshrc
$ cd foo
$ echo "layout python" > .envrc
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
$ direnv allow
direnv: loading .envrc
direnv: export +VIRTUAL_ENV ~PATH
_

これでvirtualenvに入るはずです。 _pip freeze_を実行してテストし、virtualenv固有のパッケージがインストールされていることを確認できます。非アクティブ化するには

_$ cd ..
direnv: unloading
_
5
mc_kaiser

後世のために:@MS_のソリューションを使用しましたが、あるプロジェクトから別のプロジェクトに直接cdingを実行すると、古いvirtualenvが非アクティブになりますが、新しいvirtualenvはアクティブになりません。これは、この問題を解決するソリューションのわずかに変更されたバージョンです。

# auto activate virtualenv
# Modified solution based on https://stackoverflow.com/questions/45216663/how-to-automatically-activate-virtualenvs-when-cding-into-a-directory/56309561#56309561
function cd() {
  builtin cd "$@"

  ## Default path to virtualenv in your projects
  DEFAULT_ENV_PATH="./env"

  ## If env folder is found then activate the vitualenv
  function activate_venv() {
    if [[ -f "${DEFAULT_ENV_PATH}/bin/activate" ]] ; then 
      source "${DEFAULT_ENV_PATH}/bin/activate"
      echo "Activating ${VIRTUAL_ENV}"
    fi
  }

  if [[ -z "$VIRTUAL_ENV" ]] ; then
    activate_venv
  else
    ## check the current folder belong to earlier VIRTUAL_ENV folder
    # if yes then do nothing
    # else deactivate then run a new env folder check
      parentdir="$(dirname ${VIRTUAL_ENV})"
      if [[ "$PWD"/ != "$parentdir"/* ]] ; then
        echo "Deactivating ${VIRTUAL_ENV}"
        deactivate
        activate_venv
      fi
  fi
}
1

farによる最も簡単なオプション(2019以降)は、~/.zshrcvirtualenvwrapperpluginsを追加することです

例えば:

plugins=(
  git pip python brew virtualenvwrapper
)
1
Roman

これは私の解決策です:

  • 現在アクティブなvenvにすでにあるかどうかをチェックし、その場合は何もしません
  • venvフォルダがある場合は、アクティブなフォルダがあればそれを無効にします
  • 古いvenvをアクティブにします。古いものがあったかどうかは関係ありません。

私のbash_aliases

function cd() {
    builtin cd "$@"

    if [ $(dirname "$VIRTUAL_ENV") == $(pwd) ] ; then
        # Already at the active virtual env
        return
    fi

    if [[ -d ./venv ]] ; then
        if type deactivate > /dev/null 2>&1 ; then
            printf "Deactivating virtualenv %s\n" "$VIRTUAL_ENV"
            deactivate
        fi

        source ./venv/bin/activate
        printf "Setting up   virtualenv %s\n" "$VIRTUAL_ENV"
    fi
}
0
Gauthier

@MS_のソリューションに基づく:

function cd() {
  builtin cd "$@"

  ## If env folder is found then activate the vitualenv
  if [[ -d ./venv ]] ; then
    source ./venv/bin/activate
  fi

  if [[ -n "$VIRTUAL_ENV" ]] ; then
    ## check the current folder belong to earlier VIRTUAL_ENV folder
    # if yes then do nothing
    # else deactivate
      parentdir="$(dirname "$VIRTUAL_ENV")"
      if [[ "$PWD"/ != "$parentdir"/* ]] ; then
        deactivate
      fi
  fi
}
0
Jonny Shanahan

これが(まだ)仮想環境を自動的にアクティブにする別のソリューションです。これは、すでにここに投稿されているいくつかの回答に基づいています。

これはany仮想環境の名前またはディレクトリ(./env./venvなどだけでなく)で機能します。サブディレクトリ、および仮想環境(親)フォルダーのシンボリックリンクへのcd- ingもサポートします。

このコードは、特定の名前付きディレクトリの代わりにpyvenv.cfgファイルを検索します。現在のフォルダのサブディレクトリ内で見つかった場合、環境は自動的にアクティブになります。仮想環境内に入ると、その状態は、親仮想環境ディレクトリから移動するまで保持されます。その時点で環境は非アクティブ化されます。

これを.bashrcまたは.bash_profileの中に入れます。

function cd() {
  builtin cd "$@"

  if [[ -z "$VIRTUAL_ENV" ]] ; then
      # If config file is found -> activate the vitual environment
      venv_cfg_filepath=$(find . -maxdepth 2 -type f -name 'pyvenv.cfg' 2> /dev/null)
      if [[ -z "$venv_cfg_filepath" ]]; then
        return # no config file found
      fi

      venv_filepath=$(cut -d '/' -f -2 <<< ${venv_cfg_filepath})
      if [[ -d "$venv_filepath" ]] ; then
        source "${venv_filepath}"/bin/activate
      fi
  else
    # If the current directory is not contained 
    # within the venv parent directory -> deactivate the venv.
      cur_dir=$(pwd -P)
      venv_dir="$(dirname "$VIRTUAL_ENV")"
      if [[ "$cur_dir"/ != "$venv_dir"/* ]] ; then
        deactivate
      fi
  fi
}

個人的には、どの仮想環境でも機能するはずなので、ここでの多くのソリューションの改善だと思います

0
Jake Tesler

これはcd'ingを使用しないソリューションです。zshをsetop auto_cdに設定すると、cdを使用せずにディレクトリを変更できます。ディレクトリ名を入力してEnterキーを押すだけです。それは上記の解決策の妨げです:

    # auto activate virtualenv
# Modified solution based on https://stackoverflow.com/questions/45216663/how-to-automatically-activate-virtualenvs-when-cding-into-a-directory/56309561#56309561
function auto_active_env() {

  ## Default path to virtualenv in your projects
  DEFAULT_ENV_PATH="./env"

  ## If env folder is found then activate the vitualenv
  function activate_venv() {
    if [[ -f "${DEFAULT_ENV_PATH}/bin/activate" ]] ; then 
      source "${DEFAULT_ENV_PATH}/bin/activate"
      echo "Activating ${VIRTUAL_ENV}"
    fi
  }

  if [[ -z "$VIRTUAL_ENV" ]] ; then
    activate_venv
  else
    ## check the current folder belong to earlier VIRTUAL_ENV folder
    # if yes then do nothing
    # else deactivate then run a new env folder check
      parentdir="$(dirname ${VIRTUAL_ENV})"
      if [[ "$PWD"/ != "$parentdir"/* ]] ; then
        echo "Deactivating ${VIRTUAL_ENV}"
        deactivate
        activate_venv
      fi
  fi
}
chpwd_functions=(${chpwd_functions[@]} "auto_active_env")
0
yattara

これは私の解決策です:

  1. VIRTUAL_ENVが設定されていない場合:
    1. 仮想環境内にあるかどうかを確認します
    2. はいの場合、それをアクティブにします
  2. それ以外の場合(VIRTUAL_ENVが定義されています)、現在のフォルダーが$ VIRTUAL_ENVで始まる(/venv部分を削除する)ことを確認し、非アクティブ化コマンドが存在することを確認します
    1. 環境を非アクティブ化

これはスクリプトです:

function cd() {
  builtin cd $1

  if [[ -z "${VIRTUAL_ENV}" ]]; then
    if [[ -d ./venv && -f ./venv/bin/activate ]]; then
      source ./venv/bin/activate
    fi
  Elif [[ ! "$(pwd)" == ${VIRTUAL_ENV:0:n-5}* && ! -z "$(command -v deactivate)" ]]; then
    deactivate
  fi
}

:これを.bashrcに追加する必要があります。それが機能しない場合は、.profileがコマンドを上書きしていないかどうかを確認してください(私に起こりました)

0
gfournier