Bashスクリプトでvirtualenv activateをソースする方法


96

Python virtualenvをアクティブにするBashスクリプトをどのように作成しますか?

私は次のようなディレクトリ構造を持っています:

.env
    bin
        activate
        ...other virtualenv files...
src
    shell.sh
    ...my code...

私はvirtualenvをアクティブにできます:

user@localhost:src$ . ../.env/bin/activate
(.env)user@localhost:src$

ただし、Bashスクリプトから同じことを行っても何も起こりません。

user@localhost:src$ cat shell.sh
#!/bin/bash
. ../.env/bin/activate
user@localhost:src$ ./shell.sh
user@localhost:src$ 

何が悪いのですか?


6
シェルスクリプトを実行すると、実際には新しいシェルが作成されます。使用のポイントはsource、現在のシェルで何かを変更することです。フルパスを使用してvirtualenvのpythonを使用できます./env/bin/python
Pablo Navarro

@NgureNyaga、いいえ、その質問は私の質問と同じではありません。彼らは、任意の場所から調達する方法を尋ねています。私はすでにこれを行う方法を知っています。カスタムbashスクリプト内でソーシングし、ソースを維持する方法を尋ねています。
セリン、

回答:


76

ソースを取得するときは、アクティブ化スクリプトをアクティブなシェルにロードします。

スクリプトでそれを実行するときは、スクリプトを終了すると終了するシェルにそれをロードし、元のアクティブ化されていないシェルに戻ります。

あなたの最良の選択肢は、関数でそれを行うことです

activate () {
  . ../.env/bin/activate
}

またはエイリアス

alias activate=". ../.env/bin/activate"

お役に立てれば。


Windowsの場合c:\ tutorial>。\ env \ Scripts \ activate
max4ever

5
ソースを作成したときに何が起こっているのかまったくわかりませんでした。これにより、bashスクリプトが大幅に変更されました。ありがとうございました!
Robert Townley、2016年

1
あなたのエイリアスのアイデアは私にとってもうまくいきました。ただメモ:それを機能させるには、.zshrcスクリプト(またはbashユーザーの場合は.bashrc)にそれ(エイリアスabcdef = "source ... / bin / activate")を配置する必要がありました。
Shahins 2016

これは、virtualenvがデフォルトのフォルダー名を使用している場合に最適なソリューションです。以前はフォルダーに複数のリポジトリがあり、virtualenvsを混乱させていました。今、このデフォルトに切り替えました。
3manuek

3
私はbashをはじめて使用するのが初めてです。この例を拡張して、スクリプト全体を表示できますか?
AljoSt 2018

54

ソースを使用してbashスクリプトを呼び出す必要があります。

次に例を示します。

#!/bin/bash
# Let's call this script venv.sh
source "<absolute_path_recommended_here>/.env/bin/activate"

シェルでそれを次のように呼び出すだけです:

> source venv.sh

または@outmindが示唆したように:(これはzshでは機能しないことに注意してください)

> . venv.sh

シェルの指示がプロンプトに表示されます。


2
または単に「。venv.sh」
2016

私がしようとするものに関係なく、これはsource "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"生成:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

またwhich source、シェルプロンプトで入力しても何も表示されませんが、source venv3/bin/activate期待どおりにvenvを開きます。...

なぜこれは機能しますが、source ./env/bin/activate(同じ#!/bin/bashプレフィックスで)機能しませんか?引用符を使用することとしないことの違いは何ですか?
ブラックサイト

引用符なしでスクリプト内のソースを使用しても問題ありません。source ./env/bin/activateこれはあなたが正しく走っているパスに関連しているので問題がありますか?スクリプト内のディレクトリを変更すると、相対的に移動できます。
フラビオガルシア

13

シェルプロンプトに「(.env)」プレフィックスは追加されませんが、このスクリプトは期待どおりに動作することがわかりました。

#!/bin/bash
script_dir=`dirname $0`
cd $script_dir
/bin/bash -c ". ../.env/bin/activate; exec /bin/bash -i"

例えば

user@localhost:~/src$ which pip
/usr/local/bin/pip
user@localhost:~/src$ which python
/usr/bin/python
user@localhost:~/src$ ./shell
user@localhost:~/src$ which pip
~/.env/bin/pip
user@localhost:~/src$ which python
~/.env/bin/python
user@localhost:~/src$ exit
exit

5
技術的には、サブシェルを生成しています。これは必ずしも問題ではありませんが、OPについてそれを詳しく説明する必要があります。
richo '30年

うまくいきましたが、以前は「アクティベート」ファイルに許可を与える必要がありました。
エイドリアン・ロペス

1
これは2019年に機能します!macosで私はに変更しなければなりませんでし/bin/bash/usr/bin/env bash
valem

2020年にUbuntu 18.04 AWS EC2で動作します。同じロジックを使用してどのように非アクティブ化するのでしょうか。
CSFジュニア

あなたdeactivateとサブシェルからexitか、Ctrl + Dを
Alexxロシュ

10

ソーシングは、現在のシェルでシェルコマンドを実行します。上記のようにスクリプト内でソースを作成すると、そのスクリプトの環境に影響を与えますが、スクリプトが終了すると、環境の変更は元に戻されます。これは、スクリプトがスコープから外れたためです。

virtualenvでシェルコマンドを実行することが目的の場合は、アクティブ化スクリプトをソースした後、スクリプトで実行できます。virtualenv内のシェルと対話することが目的の場合は、環境を継承するスクリプト内にサブシェルを生成できます。


2

これが私がよく使うスクリプトです。実行する$ source script_name

#!/bin/bash -x
PWD=`pwd`
/usr/local/bin/virtualenv --python=python3 venv
echo $PWD
activate () {
    . $PWD/venv/bin/activate
}

activate

1

bashスクリプトを調達する目的は何ですか?

  1. 複数のvirtualenvを切り替えるか、1つのvirtualenvにすばやく入るつもりなら、試しましたvirtualenvwrapperか?などworkon venv、多くのユーティリティを提供mkvirtualenv venvします。

  2. 特定のvirtualenvでPythonスクリプトを実行するだけの場合は、を使用/path/to/venv/bin/python script.pyして実行します。


実は、workon ...bashスクリプトから呼び出したいのですが。(起動時に毎回後でさらに実行したいので。)しかし、それを動作させる方法を見つけることができません。
ダニエルB.

1

サブシェルを使用してこれを実行して、使用方法をより適切に含めることもできます。これが実際の例です。

#!/bin/bash

commandA --args

# Run commandB in a subshell and collect its output in $VAR
# NOTE
#  - PATH is only modified as an example
#  - output beyond a single value may not be captured without quoting
#  - it is important to discard (or separate) virtualenv activation stdout
#    if the stdout of commandB is to be captured
#
VAR=$(
    PATH="/opt/bin/foo:$PATH"
    . /path/to/activate > /dev/null  # activate virtualenv
    commandB  # tool from /opt/bin/ which requires virtualenv
)

# Use the output from commandB later
commandC "$VAR"

このスタイルは、次の場合に特に役立ちます

  • の異なるバージョンcommandAまたはcommandCが存在する/opt/bin
  • commandBシステムに存在するPATHか、非常に一般的です
  • これらのコマンドはvirtualenvで失敗します
  • さまざまな異なるvirtualenvが必要です

を二重引用符で囲むことを忘れないでください。そうしないと$(...)、出力に含まれるスペースとタブが失われます。
エリック

"${VAR}"完全に"$VAR"二重引用符の方が強力なので、シェル変数を囲む中括弧は不要です。例外は、たとえば次のような修飾子を使用する場合です"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binスペースとタブのあるパスを処理するには、適切な引用が必要です。
エリック

@エリック、ありがとうございます。ただし、edit投稿の下のボタンを使用して、変更を提案できます。さらに、多くの場合それは安全上の要件であり重要ですが、意図的にイワナを追加IFSする人PATHは誰でもテロリストであることを知らせてください。
ti7

0

1行で複数のコマンドを使用する必要があります。例えば:

os.system(". Projects/virenv/bin/activate && python Projects/virenv/django-project/manage.py runserver")

仮想環境を1行でアクティブ化すると、他のコマンド行を忘れてしまうと思います。1行で複数のコマンドを使用することでこれを防ぐことができます。それは私のために働いた:)


0

私がvenvを学んでいたときに、それをアクティブにする方法を思い出させるスクリプトを作成しました。

#!/bin/sh
# init_venv.sh
if [ -d "./bin" ];then
  echo "[info] Ctrl+d to deactivate"
  bash -c ". bin/activate; exec /usr/bin/env bash --rcfile <(echo 'PS1=\"(venv)\${PS1}\"') -i"
fi

これには、プロンプトを変更するという利点があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.