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)
希望这可以帮助.
小智 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指示将放在你的提示上.
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)
Sourcing在您当前的shell中运行shell命令.当您在上面执行脚本内部时,您正在影响该脚本的环境,但是当脚本退出时,环境更改将被撤消,因为它们已经有效地超出了范围.
如果您的目的是在virtualenv中运行shell命令,则可以在获取激活脚本后在脚本中执行此操作.如果您的目的是与virtualenv中的shell进行交互,那么您可以在脚本中生成一个继承环境的子shell.
这是我经常使用的脚本。运行它作为$ 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)
您还可以使用子 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)
这种风格在以下情况下特别有用:
commandA或commandC存在于/opt/bincommandB系统中存在PATH或者很常见采购 bash 脚本有什么用?
如果您打算在多个 virtualenv 之间切换或快速进入一个 virtualenv,您尝试过吗virtualenvwrapper?它提供了很多实用工具,例如workon venv,mkvirtualenv venv等等。
如果您只是在某个 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)
它不是防弹的,但它很容易理解并且可以完成它的工作。