如何在Bash脚本中激活virtualenv激活

Cer*_*rin 78 python bash virtualenv

如何创建一个Bash脚本来激活Python virtualenv?

我有一个目录结构,如:

.env
    bin
        activate
        ...other virtualenv files...
src
    shell.sh
    ...my code...
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方式激活我的virtualenv:

user@localhost:src$ . ../.env/bin/activate
(.env)user@localhost:src$
Run Code Online (Sandbox Code Playgroud)

但是,从Bash脚本执行相同操作无效:

user@localhost:src$ cat shell.sh
#!/bin/bash
. ../.env/bin/activate
user@localhost:src$ ./shell.sh
user@localhost:src$ 
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

ric*_*cho 61

在您获取源代码时,您将激活脚本加载到活动shell中.

当您在脚本中执行此操作时,将其加载到该脚本中,该脚本在脚本完成时退出,并且您将返回到原始的未激活shell.

你最好的选择是在一个函数中做到这一点

activate () {
  . ../.env/bin/activate
}
Run Code Online (Sandbox Code Playgroud)

或别名

alias activate=". ../.env/bin/activate"
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 我完全不知道当我做源代码时发生的事情这已经大大改变了我的bash脚本编写效果.谢谢! (3认同)
  • 你的别名想法对我来说也很有效。请注意:我必须将其(别名 abcdef="source .../bin/activate")放入我的 .zshrc 脚本(或 bash 用户的 .bashrc)中才能正常工作。 (3认同)
  • 对于 Windows c:\tutorial>.\env\Scripts\activate (2认同)
  • 我是bash等新手.你能扩展这个例子,以便显示完整的脚本吗? (2认同)

小智 45

您应该使用source调用bash脚本.

这是一个例子:

#!/bin/bash
# Let's call this script venv.sh
source "<absolute_path_recommended_here>/.env/bin/activate"
Run Code Online (Sandbox Code Playgroud)

在你的shell上只需调用它:

> source venv.sh
Run Code Online (Sandbox Code Playgroud)

或者@outmind建议:(注意这不适用于zsh)

> . venv.sh
Run Code Online (Sandbox Code Playgroud)

你去了,shell指示将放在你的提示上.

  • 为什么这可以工作,但 `source ./env/bin/activate` (具有相同的 `#!/bin/bash` 前缀)却不能?使用引号和不使用引号有什么区别? (4认同)
  • 甚至只是".venv.sh" (2认同)

Cer*_*rin 13

虽然它没有在shell提示符中添加"(.env)"前缀,但我发现此脚本按预期工作.

#!/bin/bash
script_dir=`dirname $0`
cd $script_dir
/bin/bash -c ". ../.env/bin/activate; exec /bin/bash -i"
Run Code Online (Sandbox Code Playgroud)

例如

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
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,你正在产生一个子壳.这不一定是个问题,但你应该为OP拼出这个问题. (4认同)

zig*_*igg 8

Sourcing在您当前的shell中运行shell命令.当您在上面执行脚本内部时,您正在影响该脚本的环境,但是当脚本退出时,环境更改将被撤消,因为它们已经有效地超出了范围.

如果您的目的是在virtualenv中运行shell命令,则可以在获取激活脚本后在脚本中执行此操作.如果您的目的是与virtualenv中的shell进行交互,那么您可以在脚本中生成一个继承环境的子shell.


San*_*512 8

这是我经常使用的脚本。运行它作为$ source script_name

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

activate
Run Code Online (Sandbox Code Playgroud)


ti7*_*ti7 6

您还可以使用子 shell 来更好地包含您的用法 - 这是一个实际示例:

#!/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"
Run Code Online (Sandbox Code Playgroud)

这种风格在以下情况下特别有用:

  • 不同版本commandAcommandC存在于/opt/bin
  • commandB系统中存在PATH或者很常见
  • 这些命令在 virtualenv 下失败
  • 需要多种不同的虚拟环境


iMo*_*om0 5

采购 bash 脚本有什么用?

  1. 如果您打算在多个 virtualenv 之间切换或快速进入一个 virtualenv,您尝试过吗virtualenvwrapper?它提供了很多实用工具,例如workon venvmkvirtualenv venv等等。

  2. 如果您只是在某个 virtualenv 中运行 python 脚本,请使用/path/to/venv/bin/python script.py来运行它。


小智 5

正如其他人已经指出的那样,您做错的不是采购您创建的脚本。当您按照所示方式运行脚本时,它会创建一个新的 shell,该 shell 会激活虚拟环境,然后退出,因此运行脚本的原始 shell 不会发生任何更改。

您需要获取该脚本的源代码,这将使其在您当前的 shell 中运行。

您可以通过致电source shell.sh. shell.sh

为了确保脚本是源代码而不是正常执行的,最好在脚本中进行一些检查来提醒您,例如我使用的脚本是这样的:

#!/bin/bash
if [[ "$0" = "$BASH_SOURCE" ]]; then
    echo "Needs to be run using source: . activate_venv.sh"

else
    VENVPATH="venv/bin/activate"
    if [[ $# -eq 1 ]]; then 
        if [ -d $1 ]; then
            VENVPATH="$1/bin/activate"
        else
            echo "Virtual environment $1 not found"
            return
        fi

    elif [ -d "venv" ]; then 
        VENVPATH="venv/bin/activate"

    elif [-d "env"]; then 
        VENVPATH="env/bin/activate"
    fi

    echo "Activating virtual environment $VENVPATH"
    source "$VENVPATH"
fi
Run Code Online (Sandbox Code Playgroud)

它不是防弹的,但它很容易理解并且可以完成它的工作。