如何从bash脚本中停用virtualenv

时间:2015-04-09 17:54:55

标签: python virtualenv

我是shell脚本的新手,但我想制作一个bash脚本,用于使用virtualenv激活/停用虚拟环境。 然后我想像Ubuntu中的服务一样使用这个脚本将它复制到/etc/init.d文件夹中。

在我的脚本中,我有一个这样的变量: VENV=/opt/odoo/odoo_server/venv_oddo/bin

此变量表示虚拟环境中的bin路径。

在脚本中,我可以使用以下语句激活虚拟环境: . ${VENV}/activate

这是可能的,因为activate是虚拟环境中bin目录中的文件。

但我不知道在我的脚本中使用的语句来停用我的虚拟环境。 我不能这样做:. ${VENV}/deactivate

问题在于,不存在名为deactivate的文件,但是取消激活是虚拟环境中bin / activate文件中的一个函数。

6 个答案:

答案 0 :(得分:6)

只需deactivate。只要您使用bash,它就可以在脚本和命令行中使用。

编辑:在大多数情况下,最好在脚本和服务中拼写完整的python路径。它是无状态的,更便携,几乎无处不在。所以不要做

. $VENV/bin/activate
/path/to/my/script.py --parameters

通常最好做

$VENV/bin/python /path/to/my/script --parameters

相信我,它会节省您的调试时间)

答案 1 :(得分:4)

很难提供这样有用的服务。

. ${VENV}/activate # note the dot

source ${VENV}/activate

source activate脚本,即运行其内容,就好像它们是您提供源代码的shell或脚本的一部分virtualenvironment' activate is designed for this usage。相反,只需使用

执行脚本
${VENV}/activate # note: NO dot and NO 'source' command

将在子shell中运行其内容并且不会产生任何有用的效果。

但是,您的服务脚本已经在自己的子shell中运行。因此,除了作为服务启动过程的一部分运行的任何python命令外,它不会产生任何影响。

从好的方面来说,你甚至不必关心去激活环境,除非你想在服务启动过程中运行更多的python内容,但是在你的virtualenv之外。

答案 2 :(得分:2)

deactivate"命令"由virtualenvwrapper提供的实际上是一个shell函数,同样适用于workon。如果您有虚拟环境,则可以使用typeset -F列出这些功能的名称。

为了在脚本中使用它们,需要在那里定义它们,因为shell函数不会传播到子shell。

要定义这些函数,请在shell脚本中找到要调用这些函数的virtualenvwrapper.sh脚本,例如:

source $(which virtualenvwrapper.sh)

这允许您在shell脚本中调用这些函数,就像在shell中一样:

deactivate

更新:我所描述的内容适用于virtualenvwrapper提供的其他功能(例如workon)。我错误地认为它也适用于停用,但是那个是一个更复杂的情况,因为它是一个仅在运行workonactivate的shell中定义的函数。

答案 3 :(得分:0)

复制$ {VENV} / activate。

中的停用代码

粘贴你的〜/ .bashrc

deactivate() {
    # reset old environment variables
    if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
        PATH="$_OLD_VIRTUAL_PATH"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then
        PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
        export PYTHONHOME
        unset _OLD_VIRTUAL_PYTHONHOME
    fi

    # This should detect bash and zsh, which have a hash command that must
    # be called to get it to forget past commands.  Without forgetting
    # past commands the $PATH changes we made may not be respected
    if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
        hash -r
    fi

    if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
        PS1="$_OLD_VIRTUAL_PS1"
        export PS1
        unset _OLD_VIRTUAL_PS1
    fi

    unset VIRTUAL_ENV
    if [ ! "$1" = "nondestructive" ] ; then
        # Self destruct!
        unset -f deactivate
    fi
}

运行命令。

$ $VENV/activate
$ deactivate

我以这种方式有选择地使用python 2.7和python 3.5没有问题。

我想知道负面评价的原因。

答案 4 :(得分:0)

在下面使用:

declare -Ff deactivate  && deactivate

由于无法通过在〜/ bin中查找这样的命令的常规方法来发现通过源〜/ bin / activate创建的停用功能,因此您可能希望创建一个仅执行停用功能的命令。

问题在于,如果在不使用venv的情况下意外执行了名为deactivate的脚本,而该脚本包含一个停用的命令,则会导致无限循环。一个常见的错误。

只有在功能存在(即通过激活源代码创建)的情况下才执行停用命令,可以避免这种情况。

答案 5 :(得分:0)

如果您只需要以编程方式禁用/更改 virtualenv,您可以使用 shell 函数而不是 shell 脚本。例如,放在 ~/.bashrc~/.bash_aliases(如果已设置)或 ~/.zshrc~/.zsh_aliases(如果您使用 zsh)的末尾:

function ch() {

  # change this to your directory
  cd ~/git-things/my_other_py_project

  # this works, as a shell function won't spawn a subshell as the script would
  deactivate

  # re-source to change the virtualenv (my use case; change to fit yours)
  source .venv-myotherpyproject/bin/activate

}

重新启动 shell 或重新获取您使用 source ~/.zsh_aliases 更改的文件并使用命令 ch 执行该函数。