Come eseguire l'attivazione di virtualenv in uno script Bash


99

Come si crea uno script Bash per attivare un virtualenv Python?

Ho una struttura di directory come:

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

Posso attivare il mio virtualenv tramite:

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

Tuttavia, fare lo stesso da uno script Bash non fa nulla:

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

Che cosa sto facendo di sbagliato?


6
Quando esegui uno script di shell, in realtà stai creando una nuova shell. Lo scopo dell'utilizzo sourceè cambiare qualcosa nella shell corrente. Puoi usare il python di virtualenv usando il percorso completo ./env/bin/python.
Pablo Navarro

@NgureNyaga, No, questa domanda non è uguale alla mia. Chiedono come procurarsi da una posizione arbitraria. So già come farlo. Sto chiedendo come creare una fonte all'interno di uno script bash personalizzato e mantenere la fonte.
Cerin

Risposte:


79

Quando esegui i sorgenti, stai caricando lo script di attivazione nella tua shell attiva.

Quando lo fai in uno script, lo carichi in quella shell che esce al termine dello script e torni alla shell originale, non attivata.

La tua migliore opzione sarebbe farlo in una funzione

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

o un alias

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

Spero che questo ti aiuti.


per windows c: \ tutorial>. \ env \ Scripts \
activation

6
Non avevo assolutamente idea che fosse quello che stava succedendo quando ho creato il sorgente. Questo ha cambiato enormemente il mio script di bash in meglio. Grazie!
Robert Townley,

1
La tua idea di alias ha funzionato bene anche per me. Solo una nota: ho dovuto metterlo (alias abcdef = "source ... / bin / activation") nel mio script .zshrc (o .bashrc per gli utenti bash) perché funzionasse.
shahins

Questa è una buona soluzione se hai i tuoi virtualenvs usando il nome della cartella predefinito. Avevo più di un repository nella cartella, facendo un pasticcio su virtualenvs. Sono passato a questa impostazione predefinita ora.
3manuek

3
Sono abbastanza nuovo a bash ecc. Puoi espandere questo esempio in modo che mostri lo script completo?
AljoSt

57

Dovresti chiamare lo script bash usando source.

Ecco un esempio:

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

Sul tuo guscio chiamalo così:

> source venv.sh

O come suggerito da @outmind: (Nota che questo non funziona con zsh)

> . venv.sh

Ecco fatto, l'indicazione della shell verrà posizionata sul tuo prompt.


2
o anche solo ". venv.sh"
outmind

non importa cosa provo, questo source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"produce:/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

Inoltre non ottengo nulla quando digito which sourceal prompt della shell, tuttavia, source venv3/bin/activatefa quello che mi aspetto e apro il venv. ...

Perché funziona, ma source ./env/bin/activate(con lo stesso #!/bin/bashprefisso) no? Qual è la differenza tra usare le virgolette e non?
blacksite

Non ho problemi a utilizzare il sorgente all'interno dello script senza virgolette. Vedo un problema source ./env/bin/activateperché è relativo al percorso che stai percorrendo, giusto? Se cambi la directory all'interno dello script, puoi andare relativo.
Flavio Garcia

13

Sebbene non aggiunga il prefisso "(.env)" al prompt della shell, ho riscontrato che questo script funziona come previsto.

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

per esempio

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
tecnicamente stai generando una subshell. Non è necessariamente un problema, ma dovresti spiegarlo per l'OP.
richo

Ha funzionato, ma prima ho dovuto dare il permesso al mio file di "attivazione".
Adrian Lopez

1
Funziona nel 2019! Su macos ho solo dovuto cambiare /bin/bashin/usr/bin/env bash
valem

Funziona in Ubuntu 18.04 AWS EC2 nel 2020. Mi chiedo come faccio a disattivare utilizzando la stessa logica?
CSF Junior

Tu deactivatedalla subshell con exito Ctrl + d
Alexx Roche

10

Il sourcing esegue i comandi della shell nella shell corrente. Quando provieni all'interno di uno script come stai facendo sopra, stai influenzando l'ambiente per quello script, ma quando lo script esce, le modifiche all'ambiente vengono annullate, poiché sono effettivamente fuori portata.

Se il tuo intento è eseguire i comandi della shell in virtualenv, puoi farlo nel tuo script dopo aver acquisito lo script di attivazione. Se il tuo intento è interagire con una shell all'interno di virtualenv, puoi generare una sub-shell all'interno del tuo script che erediterebbe l'ambiente.


2

Ecco lo script che uso spesso. Eseguilo come$ source script_name

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

activate

1

A cosa serve procurarsi lo script bash?

  1. Se intendi passare da più virtualenv o inserire rapidamente una virtualenv, hai provato virtualenvwrapper? Esso fornisce un sacco di utils come workon venv, mkvirtualenv venve così via.

  2. Se esegui solo uno script python in alcuni virtualenv, usalo /path/to/venv/bin/python script.pyper eseguirlo.


In realtà, vorrei chiamare workon ...da uno script bash. (Perché voglio eseguire altre cose in seguito ogni volta al suo avvio.) Non riesco a trovare un modo per farlo funzionare, però.
Daniel B.

1

Puoi anche farlo usando una subshell per contenere meglio il tuo utilizzo - ecco un esempio pratico:

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

Questo stile è particolarmente utile quando

  • una versione diversa di commandAo commandCesiste sotto/opt/bin
  • commandB esiste nel sistema PATH o è molto comune
  • questi comandi falliscono sotto virtualenv
  • uno ha bisogno di una varietà di virtualenv diversi

Non dimenticare di virgolette due volte $(...)o ti mancheranno spazi e tabulazioni contenuti nell'output.
Eric,

"${VAR}"è strettamente equivalente al fatto "$VAR"che non hai bisogno di parentesi graffe attorno alle variabili di shell perché le virgolette doppie sono in realtà più potenti. L'eccezione è quando si utilizzano modificatori come, ad esempio"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binnecessita di quotazioni appropriate per gestire i percorsi con spazi e tabulazioni.
Eric,

@ Eric Grazie, anche se puoi utilizzare il editpulsante sotto i post per suggerire modifiche! Inoltre, sappi che sebbene sia spesso un requisito e importante per la sicurezza, chiunque aggiunga consapevolmente IFScaratteri a PATHè un terrorista.
ti7

0

Dovresti usare più comandi in una riga. per esempio:

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

quando attivi il tuo ambiente virtuale in una riga, penso che si dimentichi di altre righe di comando e puoi impedirlo utilizzando più comandi in una riga. Ha funzionato per me :)


0

Quando stavo imparando venv ho creato uno script per ricordarmi come attivarlo.

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

Questo ha il vantaggio che cambia il prompt.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.