So aktivieren Sie virtualenv in einem Bash-Skript


96

Wie erstellt man ein Bash-Skript, um eine Python-Virtualenv zu aktivieren?

Ich habe eine Verzeichnisstruktur wie:

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

Ich kann meine virtuelle Umgebung aktivieren durch:

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

Dasselbe mit einem Bash-Skript zu tun, bewirkt jedoch nichts:

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

Was mache ich falsch?


6
Wenn Sie ein Shell-Skript ausführen, erstellen Sie tatsächlich eine neue Shell. Der Sinn der Verwendung sourcebesteht darin, etwas in der aktuellen Shell zu ändern. Sie können die Python des virtualenv über den vollständigen Pfad verwenden ./env/bin/python.
Pablo Navarro

@NgureNyaga, Nein, diese Frage ist nicht die gleiche wie meine. Sie fragen, wie sie von einem beliebigen Ort aus beziehen sollen. Ich weiß schon, wie das geht. Ich frage, wie man innerhalb eines benutzerdefinierten Bash-Skripts eine Quelle erstellt und die Quelle verwaltet.
Cerin

Antworten:


76

Wenn Sie eine Quelle erstellen, laden Sie das Aktivierungsskript in Ihre aktive Shell.

Wenn Sie dies in einem Skript tun, laden Sie es in die Shell, die beendet wird, wenn Ihr Skript beendet ist und Sie zu Ihrer ursprünglichen, nicht aktivierten Shell zurückkehren.

Ihre beste Option wäre, dies in einer Funktion zu tun

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

oder ein Alias

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

Hoffe das hilft.


für Windows C: \ Tutorial>. \ env \ Scripts \ aktivieren
max4ever

5
Ich hatte absolut keine Ahnung, was passiert ist, als ich die Quelle erstellt habe. Dies hat mein Bash-Scripting erheblich zum Besseren verändert. Danke dir!
Robert Townley

1
Ihre Alias-Idee hat auch bei mir gut funktioniert. Nur eine Anmerkung: Ich musste es (alias abcdef = "source ... / bin / enabled") in mein .zshrc-Skript (oder .bashrc für die Bash-Benutzer) einfügen, damit es funktioniert.
Shahins

Dies ist eine gute Lösung, wenn Ihre virtuellen Umgebungen den Standardordnernamen verwenden. Früher hatte ich mehr als ein Repo im Ordner, was die virtuellen Umgebungen durcheinander brachte. Ich habe jetzt zu dieser Standardeinstellung gewechselt.
3manuek

3
Ich bin ziemlich neu in Bash usw. Können Sie dieses Beispiel so erweitern, dass es das vollständige Skript zeigt?
AljoSt

54

Sie sollten das Bash-Skript mit source aufrufen.

Hier ist ein Beispiel:

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

Nennen Sie es auf Ihrer Shell einfach so:

> source venv.sh

Oder wie von @outmind vorgeschlagen: (Beachten Sie, dass dies mit zsh nicht funktioniert.)

> . venv.sh

Los geht's, die Shell-Anzeige wird auf Ihrer Eingabeaufforderung platziert.


2
oder auch nur ". venv.sh"
outmind

egal was ich versuche, dies source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"erzeugt:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

Ich bekomme auch nichts, wenn ich which sourcean einer Shell-Eingabeaufforderung source venv3/bin/activatetippe , aber das tue, was ich erwarte und das Venv öffne. ...

Warum funktioniert das, aber source ./env/bin/activate(mit demselben #!/bin/bashPräfix) nicht? Was ist der Unterschied zwischen der Verwendung von Anführungszeichen und nicht?
Blacksite

Ich habe kein Problem damit, die Quelle im Skript ohne Anführungszeichen zu verwenden. Ich sehe ein Problem mit, source ./env/bin/activateweil dies relativ zu dem Pfad ist, den Sie laufen, oder? Wenn Sie das Verzeichnis innerhalb des Skripts ändern, können Sie relativ werden.
Flavio Garcia

13

Obwohl das Präfix "(.env)" nicht zur Shell-Eingabeaufforderung hinzugefügt wird, hat dieses Skript wie erwartet funktioniert.

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

z.B

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
Technisch gesehen erzeugen Sie eine Unterschale. Es ist nicht unbedingt ein Problem, aber Sie sollten das für das OP formulieren.
Richo

Es hat funktioniert, aber ich musste vorher meine "Aktivierungs" -Datei genehmigen.
Adrian Lopez

1
Das funktioniert 2019! Auf macos Ich musste nur die ändern /bin/bashzu/usr/bin/env bash
valem

Funktioniert in Ubuntu 18.04 AWS EC2 im Jahr 2020. Ich frage mich, wie ich mit derselben Logik deaktivieren kann.
CSF Junior

Sie deactivateaus der Subshell mit exitoder Strg + d
Alexx Roche

10

Beim Sourcing werden Shell-Befehle in Ihrer aktuellen Shell ausgeführt. Wenn Sie innerhalb eines Skripts wie oben beschrieben eine Quelle erstellen, wirkt sich dies auf die Umgebung dieses Skripts aus. Wenn das Skript jedoch beendet wird, werden die Umgebungsänderungen rückgängig gemacht, da sie praktisch außerhalb des Gültigkeitsbereichs liegen.

Wenn Sie Shell-Befehle in der virtuellen Umgebung ausführen möchten, können Sie dies in Ihrem Skript tun, nachdem Sie das Aktivierungsskript bezogen haben. Wenn Sie mit einer Shell innerhalb der virtuellen Umgebung interagieren möchten, können Sie eine Sub-Shell in Ihrem Skript erzeugen, die die Umgebung erben würde.


2

Hier ist das Skript, das ich oft benutze. Führen Sie es als$ source script_name

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

activate

1

Wofür dient die Beschaffung des Bash-Skripts?

  1. Wenn Sie beabsichtigen, zwischen mehreren virtuellen Umgebungen zu wechseln oder schnell eine virtuelle Umgebung einzugeben, haben Sie es versucht virtualenvwrapper? Es bietet eine Menge utils wie workon venv, mkvirtualenv venvund so weiter.

  2. Wenn Sie nur ein Python-Skript in einer bestimmten virtuellen Umgebung ausführen, verwenden Sie es /path/to/venv/bin/python script.py, um es auszuführen.


Eigentlich möchte ich workon ...von einem Bash-Skript aus aufrufen . (Weil ich jedes Mal beim Start weitere Dinge ausführen möchte.) Ich kann jedoch keinen Weg finden, es zum Laufen zu bringen.
Daniel B.

1

Sie können dies auch mit einer Unterschale tun, um Ihre Verwendung besser einzudämmen - hier ein praktisches Beispiel:

#!/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"

Dieser Stil ist besonders hilfreich, wenn

  • eine andere Version von commandAoder commandCexistiert unter/opt/bin
  • commandBexistiert im System PATHoder ist sehr verbreitet
  • Diese Befehle schlagen unter der virtuellen Umgebung fehl
  • man braucht eine Vielzahl von verschiedenen virtuellen Umgebungen

Vergessen Sie nicht, das in doppelte Anführungszeichen zu setzen, da $(...)sonst Leerzeichen und Tabulatoren in der Ausgabe fehlen.
Eric

"${VAR}"ist genau gleichbedeutend damit, dass "$VAR"Sie keine geschweiften Klammern um Shell-Variablen benötigen, da doppelte Anführungszeichen tatsächlich leistungsfähiger sind. Die Ausnahme ist bei der Verwendung von Modifikatoren zum Beispiel mag"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binbenötigt korrekte Anführungszeichen, um Pfade mit Leerzeichen und Tabulatoren zu behandeln.
Eric

@ Eric Danke, obwohl du den editButton unter den Posts verwenden kannst , um Änderungen an ihnen vorzuschlagen! Lassen Sie uns außerdem wissen, dass jeder, der wissentlich IFSZeichen hinzufügt , PATHein Terrorist ist, obwohl dies häufig eine Anforderung und wichtig für die Sicherheit ist.
7.

0

Sie sollten mehrere Befehle in einer Zeile verwenden. beispielsweise:

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

Wenn Sie Ihre virtuelle Umgebung in einer Zeile aktivieren, werden andere Befehlszeilen vergessen, und Sie können dies verhindern, indem Sie mehrere Befehle in einer Zeile verwenden. Es hat bei mir funktioniert :)


0

Als ich venv lernte, erstellte ich ein Skript, um mich daran zu erinnern, wie man es aktiviert.

#!/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

Dies hat den Vorteil, dass die Eingabeaufforderung geändert wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.