Как получить активацию virtualenv в сценарии Bash

106

Как создать сценарий Bash для активации виртуального сервера Python?

У меня есть такая структура каталогов:

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

Я могу активировать свой виртуальный сервер:

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$ 

Что я делаю не так?

Cerin
источник
6
Когда вы запускаете сценарий оболочки, вы фактически создаете новую оболочку. Смысл использования source- изменить что-то в текущей оболочке. Вы можете использовать python virtualenv, используя полный путь ./env/bin/python.
Пабло Наварро,
@NgureNyaga, нет, этот вопрос не такой, как у меня. Они спрашивают, как получить источник из произвольного места. Я уже знаю, как это сделать. Я спрашиваю, как использовать исходный код в настраиваемом сценарии bash и поддерживать его.
Cerin

Ответы:

84

Когда вы исходите, вы загружаете скрипт активации в активную оболочку.

Когда вы делаете это в скрипте, вы загружаете его в ту оболочку, которая завершается, когда ваш скрипт завершается, и вы возвращаетесь к исходной неактивированной оболочке.

Лучшим вариантом было бы сделать это в функции

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

или псевдоним

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

Надеюсь это поможет.

рико
источник
для Windows c: \ tutorial>. \ env \ Scripts \ activate
max4ever
7
Я понятия не имел, что происходило, когда я делал исходный код. Это сильно изменило мои сценарии bash к лучшему. Спасибо!
Роберт Таунли
1
Ваша идея псевдонима мне тоже понравилась. Просто примечание: мне пришлось поместить его (псевдоним abcdef = "source ... / bin / activate") в мой сценарий .zshrc (или .bashrc для пользователей bash), чтобы он заработал.
Shahins 06
Это хорошее решение, если у вас есть виртуальные машины, использующие имя папки по умолчанию. Раньше у меня было более одного репо в папке, что создавало беспорядок в virtualenvs. Я переключился на это значение по умолчанию.
3manuek 05
3
Я новичок в bash и т. Д. Можете ли вы расширить этот пример, чтобы он показал полный сценарий?
AljoSt 05
60

Вы должны вызвать сценарий 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"
напомню
независимо от того, что я пытаюсь, это 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префиксом) нет? В чем разница между использованием кавычек и нет?
blacksite
У меня нет проблем с использованием исходного кода внутри скрипта без кавычек. Я вижу проблему, source ./env/bin/activateпотому что это связано с тем путем, по которому вы бежите, верно? Если вы измените каталог внутри скрипта, вы можете перейти в относительный.
Flavio Garcia
14

Хотя он не добавляет префикс «(.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
Cerin
источник
5
технически вы создаете подоболочку. Это не обязательно проблема, но вы должны разъяснить это для OP.
Ричо
Это сработало, но раньше мне приходилось давать разрешение на "активировать" файл.
Адриан Лопес
1
Это работает в 2019 году! На MacOS я должен был изменить /bin/bashк/usr/bin/env bash
valem
Работает в Ubuntu 18.04 AWS EC2 в 2020 году. Интересно, как мне отключить, используя ту же логику?
CSF Junior,
Вы deactivateиз подоболочки с помощью exitили Ctrl + d
Alexx Roche
10

Sourcing запускает команды оболочки в вашей текущей оболочке. Когда вы делаете исходный код внутри сценария, как вы делаете выше, вы влияете на среду для этого сценария, но когда сценарий завершается, изменения среды отменяются, поскольку они фактически вышли за пределы области видимости.

Если вы намереваетесь запускать команды оболочки в virtualenv, вы можете сделать это в своем скрипте после получения скрипта активации. Если ваше намерение состоит в том, чтобы взаимодействовать с оболочкой внутри virtualenv, вы можете создать вложенную оболочку внутри вашего скрипта, которая унаследует среду.

зигг
источник
3

Вот сценарий, который я часто использую. Запустить как$ source script_name

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

activate
Санджаи Рави
источник
2

Для чего нужен сценарий bash?

  1. Если вы собираетесь переключаться между несколькими виртуальными виртуальными машинами или быстро войти в одну виртуальную среду, вы пробовали virtualenvwrapper? Это дает много утилитами , как workon venv, mkvirtualenv venvи так далее.

  2. Если вы просто запускаете скрипт Python в определенном виртуальном окружении, используйте /path/to/venv/bin/python script.pyдля его запуска.

iMom0
источник
Собственно, я бы хотел позвонить workon ...из сценария bash. (Потому что я хочу выполнять дальнейшие действия каждый раз при его запуске.) Однако не могу найти способ заставить его работать.
Дэниел Б.
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
  • нужно множество разных виртуальных возможностей
ti7
источник
Не забудьте $(...)заключить в двойные кавычки, иначе в выводе будут отсутствовать пробелы и табуляции.
Эрик
"${VAR}"строго эквивалентно тому, что "$VAR"вам не нужны фигурные скобки вокруг переменных оболочки, потому что двойные кавычки на самом деле более эффективны. Исключение при использовании модификаторов , таких как, например"${VAR:-default_value}"
Эрик
PATH=$PATH:/opt/binтребуется правильное цитирование для обработки путей с пробелами и табуляциями.
Эрик
@Eric Спасибо, но вы можете использовать editкнопку под сообщениями, чтобы предлагать им изменения! Кроме того, пусть будет известно, что, хотя это часто является требованием и важно для безопасности, любой, кто сознательно добавляет IFSсимволы, PATHявляется террористом.
ti7
0

Вы должны использовать несколько команд в одной строке. например:

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

когда вы активируете свою виртуальную среду в одной строке, я думаю, что это забывает о других командных строках, и вы можете предотвратить это, используя несколько команд в одной строке. У меня сработало :)

Ахмадреза Пургходрат
источник
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

Это имеет то преимущество, что меняет подсказку.

Алекс Рош
источник