Jak pozyskać aktywację virtualenv w skrypcie Bash


105

Jak utworzyć skrypt Bash, aby aktywować virtualenv w języku Python?

Mam strukturę katalogów taką jak:

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

Mogę aktywować virtualenv poprzez:

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

Jednak zrobienie tego samego ze skryptu Bash nic nie robi:

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

Co ja robię źle?


6
Kiedy uruchamiasz skrypt powłoki, w rzeczywistości tworzysz nową powłokę. Celem użycia sourcejest zmiana czegoś w bieżącej powłoce. Możesz użyć Pythona virtualenv, używając pełnej ścieżki ./env/bin/python.
Pablo Navarro

@NgureNyaga, Nie, to pytanie nie jest takie samo jak moje. Pytają, jak pozyskać z dowolnej lokalizacji. Już wiem, jak to zrobić. Pytam, jak pozyskiwać źródła w niestandardowym skrypcie bash i utrzymywać źródło.
Cerin

Odpowiedzi:


83

Kiedy pobierasz źródło, ładujesz skrypt aktywacyjny do aktywnej powłoki.

Kiedy robisz to w skrypcie, ładujesz go do tej powłoki, która kończy pracę po zakończeniu skryptu i wracasz do oryginalnej, nieaktywowanej powłoki.

Najlepszym rozwiązaniem byłoby zrobienie tego w funkcji

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

lub alias

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

Mam nadzieję że to pomoże.


for windows c: \ tutorial>. \ env \ Scripts \
activ

7
Nie miałem absolutnie pojęcia, co się dzieje, kiedy tworzę źródła. To znacznie zmieniło moje skrypty basha na lepsze. Dziękuję Ci!
Robert Townley

1
Twój pomysł na alias też mi się podobał. Tylko uwaga: musiałem to umieścić (alias abcdef = "source ... / bin / activ") w moim skrypcie .zshrc (lub .bashrc dla użytkowników basha), aby działał.
shahins

Jest to dobre rozwiązanie, jeśli masz swoje virtualenvs używające domyślnej nazwy folderu. Kiedyś miałem więcej niż jedno repozytorium w folderze, robiąc bałagan na virtualenvach. Teraz przełączyłem się na to domyślne.
3manuek

3
Jestem całkiem nowy w bashu itp. Czy możesz rozszerzyć ten przykład tak, aby pokazywał pełny skrypt?
AljoSt

60

Powinieneś wywołać skrypt bash używając source.

Oto przykład:

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

Na swojej powłoce po prostu nazwij to tak:

> source venv.sh

Lub jak zasugerował @outmind: (Zauważ, że to nie działa z zsh)

> . venv.sh

Proszę, wskazanie powłoki zostanie umieszczone w twoim znaku zachęty.


2
lub nawet po prostu „. venv.sh”
przechytrzyć

bez względu na to, co próbuję, source "/home/surest/Desktop/testservers/TEST_VENV/venv3/bin/activate"daje to :/home/surest/Desktop/testservers/TEST_VENV/py3.sh: 10: /home/surest/Desktop/testservers/TEST_VENV/py3.sh: source: not found

Nic też nie dostaję, kiedy piszę which sourcew source venv3/bin/activatezachęcie powłoki, ale robi to, czego się spodziewam i otwieram venv. ...

Dlaczego to działa, ale source ./env/bin/activate(z tym samym #!/bin/bashprefiksem) nie? Jaka jest różnica między używaniem cudzysłowów a nie?
blacksite

Nie mam problemu z używaniem źródła wewnątrz skryptu bez cudzysłowów. Widzę problem, source ./env/bin/activateponieważ jest to zależne od ścieżki, którą biegniesz, prawda? Jeśli zmienisz katalog wewnątrz skryptu, możesz przejść do względnej.
Flavio Garcia

14

Chociaż nie dodaje przedrostka „(.env)” do znaku zachęty powłoki, stwierdziłem, że ten skrypt działa zgodnie z oczekiwaniami.

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

na przykład

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
technicznie tworzysz podpowłokę. Niekoniecznie jest to problem, ale powinieneś to przeliterować w OP.
richo

Zadziałało, ale wcześniej musiałem udzielić pozwolenia na mój plik „aktywuj”.
Adrian Lopez,

1
To działa w 2019 roku! Na MacOS po prostu musiałem zmienić /bin/bashna/usr/bin/env bash
valem

Działa w Ubuntu 18.04 AWS EC2 w 2020 roku. Zastanawiam się, jak dezaktywować używając tej samej logiki?
CSF Junior

Jesteś deactivatez podpowłoki za pomocą exitlub Ctrl + d
Alexx Roche

10

Sourcing uruchamia polecenia powłoki w bieżącej powłoce. Kiedy pozyskujesz źródło wewnątrz skryptu, tak jak robisz powyżej, wpływasz na środowisko tego skryptu, ale kiedy skrypt kończy pracę, zmiany środowiska są cofane, ponieważ faktycznie wyszły poza zakres.

Jeśli zamierzasz uruchamiać polecenia powłoki w virtualenv, możesz to zrobić w swoim skrypcie po pobraniu skryptu aktywacyjnego. Jeśli twoim zamiarem jest interakcja z powłoką wewnątrz virtualenv, możesz stworzyć podpowłokę wewnątrz swojego skryptu, która odziedziczy środowisko.


3

Oto skrypt, którego często używam. Uruchom to jako$ source script_name

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

activate

2

Do czego służy pozyskiwanie skryptu bash?

  1. Jeśli zamierzasz przełączać się między wieloma virtualenvami lub szybko wprowadzać jeden virtualenv, czy próbowałeś virtualenvwrapper? Zapewnia dużo utils jak workon venv, mkvirtualenv venvi tak dalej.

  2. Jeśli po prostu uruchamiasz skrypt Pythona w pewnym virtualenv, użyj go, /path/to/venv/bin/python script.pyaby go uruchomić.


Właściwie chciałbym zadzwonić workon ...ze skryptu bash. (Ponieważ chcę wykonać kolejne rzeczy później za każdym razem podczas jego uruchamiania). Nie mogę jednak znaleźć sposobu, aby to zadziałało.
Daniel B.,

1

Możesz to również zrobić za pomocą podpowłoki, aby lepiej ograniczyć użycie - oto praktyczny przykład:

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

Ten styl jest szczególnie pomocny, gdy

  • inna wersja commandAlub commandCistnieje w ramach/opt/bin
  • commandBistnieje w systemie PATHlub jest bardzo powszechne
  • te polecenia zawodzą w virtualenv
  • potrzeba wielu różnych virtualenvów

Nie zapomnij o podwójnym cudzysłowie $(...)lub w wynikach będzie brakować spacji i tabulatorów.
Eric

"${VAR}"jest ściśle równoważne z "$VAR"tym, że nie potrzebujesz nawiasów klamrowych wokół zmiennych powłoki, ponieważ podwójne cudzysłowy są w rzeczywistości potężniejsze. Wyjątkiem jest użycie modyfikatorów, takich jak na przykład"${VAR:-default_value}"
Eric

PATH=$PATH:/opt/binwymaga odpowiedniego cytowania do obsługi ścieżek ze spacjami i tabulatorami.
Eric

@Eric Dzięki, chociaż możesz użyć editprzycisku pod postami, aby zasugerować zmiany! Co więcej, niech będzie wiadomo, że chociaż jest to często wymóg i ważny dla bezpieczeństwa, każdy, kto świadomie dodaje IFSznaki, PATHjest terrorystą.
ti7

0

Powinieneś użyć wielu poleceń w jednej linii. na przykład:

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

Kiedy aktywujesz swoje wirtualne środowisko w jednej linii, myślę, że zapomina o innych wierszach poleceń i możesz temu zapobiec, używając wielu poleceń w jednym wierszu. U mnie zadziałało :)


0

Kiedy uczyłem się venv, stworzyłem skrypt, który przypomina mi, jak go aktywować.

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

Ma to tę zaletę, że zmienia monit.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.