如何在Bash脚本中激活virtualenv源


97

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

我有一个类似的目录结构:

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

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

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$ 

我究竟做错了什么?


6
运行shell脚本时,实际上是在创建一个新的shell。使用的要点source是更改当前shell中的某些内容。您可以使用完整路径使用virtualenv的python ./env/bin/python
Pablo Navarro 2012年

@NgureNyaga,不,这个问题和我的不一样。他们在问如何从任意位置获取资源。我已经知道该怎么做。我在问如何在自定义bash脚本中进行源维护并维护源。
塞林2012年

Answers:


76

当您获取资源时,您会将激活脚本加载到活动的shell中。

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

最好的选择是在函数中执行此操作

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

或别名

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

希望这可以帮助。


对于Windows c:\ tutorial>。\ env \ Scripts \ activate
max4ever 2014年

5
我绝对不知道那是我做源代码时发生的事情。这极大地改变了我的bash脚本,使情况变得更好。谢谢!
罗伯特·汤利

1
您的别名想法对我也很好。请注意:我必须将它(别名abcdef =“ source ... / bin / activate”)放在我的.zshrc脚本(对于bash用户为.bashrc)中,以使其起作用。
shahins '16

如果您的virtualenvs使用默认文件夹名称,这是一个很好的解决方案。我以前在文件夹中有多个存储库,使virtualenvs混乱不堪。我现在切换到此默认值。
3manuek '17

3
我对bash等还很陌生。可以扩展此示例,使其显示完整脚本吗?
AljoSt

54

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

这是一个例子:

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

在您的shell上这样称呼它:

> source venv.sh

或按照@outmind建议:(请注意,这不适用于zsh)

> . venv.sh

到这里,shell指示将出现在您的提示符下。


2
或什至只是“。venv.sh”
2016年

不管我尝试什么,都会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在shell提示符下键入时,我也什么也没得到,但是,source venv3/bin/activate没有达到我期望的并打开venv。...

为什么这样做有效,但source ./env/bin/activate(使用相同的#!/bin/bash前缀)却无效?使用引号和不使用引号有什么区别?
blacksite

使用脚本中没有引号的源代码我没有问题。我看到一个问题,source ./env/bin/activate因为这与您正在运行的路径有关吗?如果您在脚本内更改目录,则可以相对。
Flavio Garcia

13

尽管它没有在shell提示符中添加“(.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

5
从技术上讲,您正在生成一个子shell。这不一定是问题,但是您应该为OP阐明这一点。
richo 2012年

它起作用了,但是之前我必须授予“激活”文件的权限。
Adrian Lopez

1
这在2019年有效!在macOS上,我只需要将其更改/bin/bash/usr/bin/env bash
-valem,

将于2020年在Ubuntu 18.04 AWS EC2中运行。我想知道如何使用相同的逻辑将其停用?
CSF初中

deactivate从带有exit或Ctrl + d 的子外壳中获得
Alexx Roche

10

Sourcing在您当前的shell中运行shell命令。当像上述一样在脚本内部获取源代码时,会影响该脚本的环境,但是当脚本退出时,环境更改将被撤消,因为它们实际上已超出范围。

如果您打算在virtualenv中运行shell命令,则可以在获取激活脚本后在脚本中执行此操作。如果您打算与virtualenv内部的shell进行交互,则可以在脚本内部产生一个继承环境的子shell。


2

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

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

activate

1

采购bash脚本的目的是什么?

  1. 如果您打算在多个virtualenv之间切换或快速输入一个virtualenv,您是否尝试过virtualenvwrapper?它提供了很多像utils的的workon venvmkvirtualenv venv等等。

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


实际上,我想workon ...从bash脚本中调用。(因为我希望每次启动后都执行更多的工作。)但是,找不到找到使之工作的方法。
Daniel B.

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"

此样式在以下情况下特别有用

  • 下的commandAcommandC存在其他版本/opt/bin
  • commandB存在于系统中PATH或非常普遍
  • 这些命令在virtualenv下失败
  • 一个需要各种不同的虚拟环境

不要忘了用双引号引起来,$(...)否则您将缺少输出中包含的空格和制表符。
埃里克

"${VAR}"严格等同于"$VAR"您不需要在shell变量周围使用大括号,因为双引号实际上更有效。例外是使用修饰符,例如"${VAR:-default_value}"
Eric

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

这样做的好处是可以更改提示。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.