如何在 Bash 脚本中启动 virtualenv activate

2025-03-04 08:24:00
admin
原创
99
摘要:问题描述:如何创建 Bash 脚本来激活 Python 虚拟环境?我有一个如下的目录结构:.env bin activate ...other virtualenv files... src shell.sh ...my code... 我可以通过以下方...

问题描述:

如何创建 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$ 

我做错什么了?


解决方案 1:

您应该使用源调用 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:

当你进行源操作时,你正在将激活脚本加载到活动 shell 中。

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

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

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

或别名

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

解决方案 3:

虽然它没有在 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

解决方案 4:

源操作会在当前 shell 中运行 shell 命令。当您像上面一样在脚本内部执行源操作时,会影响该脚本的环境,但当脚本退出时,环境更改会被撤消,因为它们实际上已经超出范围。

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

解决方案 5:

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

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

activate

解决方案 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"

这种风格在以下情况下尤其有用:

  • 不同版本的commandAcommandC存在于/opt/bin

  • commandB存在于系统中PATH或非常常见

  • 这些命令在虚拟环境下失败

  • 需要各种不同的虚拟环境

解决方案 7:

正如其他人已经指出的那样,您做错的是没有获取您创建的脚本。当您按照您展示的方式运行脚本时,它会创建一个新的 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

它不是万无一失的,但它很容易理解,而且能完成它的工作。

解决方案 8:

获取 bash 脚本的目的是什么?

  1. 如果你需要在多个虚拟环境之间切换,或者快速进入一个虚拟环境,你尝试过 吗virtualenvwrapper?它提供了很多工具,比如workon venvmkvirtualenv venv等等。

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

解决方案 9:

我只是将其添加到我的 .bashrc-personal 配置文件中。

function sv () {
    if [ -d "venv" ]; then
      source "venv/bin/activate"
    else
      if [ -d ".venv" ]; then
        source ".venv/bin/activate"
      else
        echo "Error: No virtual environment detected!"
      fi
    fi
}

解决方案 10:

您应该在一行中使用多个命令。例如:

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

当您在一行中激活虚拟环境时,我认为它会忘记其他命令行,您可以通过在一行中使用多个命令来防止这种情况。它对我有用 :)

解决方案 11:

当我学习 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

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

解决方案 12:

正如其他答案所述,当您运行脚本时,它会创建一个子 shell。当脚本退出时,对该 shell 的所有修改都将丢失。

我们实际上需要运行一个虚拟环境处于活动状态的新 shell,而不是退出它。请注意,这是一个shell,而不是运行脚本之前使用的 shell。这意味着,如果您输入exit它,它将退出子 shell,并返回到上一个 shell(您运行脚本的 shell),它不会关闭您的 xterm 或其他任何东西,正如您可能预料的那样。

问题是,当我们执行 bash 时,它会读取其 rc 文件(/etc/bash.bashrc、~/.bashrc),这改变 shell 环境。解决方案是为 bash 提供一种像往常一样设置 shell 的方法,同时另外激活虚拟环境。为此,我们创建一个临时文件,重新创建原始 bash 行为,并添加一些启用 venv 所需的内容。然后我们要求 bash 使用它而不是其通常的 rc 文件。

为我们的 venv 创建一个“专用”的新 shell 的一个有益副作用是,要停用虚拟环境,只需退出 shell 即可。我在下面显示的脚本中使用它来提供“停用”选项,该选项通过向新 shell ( kill -SIGUSR1) 发送信号来起作​​用,该信号被拦截 ( trap ...) 并引发退出 shell。注意:我使用 SIGUSR1 来不干扰“正常”行为中可以设置的任何内容。

我使用的脚本:

#!/bin/bash

PYTHON=python3

myname=$(basename "$0")
mydir=$(cd $(dirname "$0") && pwd)
venv_dir="${mydir}/.venv/dev"

usage() {
    printf "Usage: %s (activate|deactivate)
" "$myname"
}

[ $# -eq 1 ] || { usage >&2; exit 1; }

in_venv() {
    [ -n "$VIRTUAL_ENV" -a "$VIRTUAL_ENV" = "$venv_dir" -a -n "$VIRTUAL_ENV_SHELL_PID" ]
}

case $1 in
    activate)
        # check if already active
        in_venv && {
            printf "Virtual environment already active
"
            exit 0
        }

        # check if created
        [ -e "$venv_dir" ] || {
            $PYTHON -m venv --clear --prompt "venv: dev" "$venv_dir" || {
                printf "Failed to initialize venv
" >&2
                exit 1
            }
        }

        # activate
        tmp_file=$(mktemp)
        cat <<EOF >"$tmp_file"
# original bash behavior
if [ -f /etc/bash.bashrc ]; then
    source /etc/bash.bashrc
fi
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

# activating venv
source "${venv_dir}/bin/activate"

# remove deactivate function:
# we don't want to call it by mistake
# and forget we have an additional shell running
unset -f deactivate

# exit venv shell
venv_deactivate() {
    printf "Exitting virtual env shell.
" >&2
    exit 0
}
trap "venv_deactivate" SIGUSR1

VIRTUAL_ENV_SHELL_PID=$$
export VIRTUAL_ENV_SHELL_PID

# remove ourself, don't let temporary files laying around
rm -f "${tmp_file}"
EOF
        exec "/bin/bash" --rcfile "$tmp_file" -i || {
            printf "Failed to execute virtual environment shell
" >&2
            exit 1
        }
    ;;
    deactivate)
        # check if active
        in_venv || {
            printf "Virtual environment not found
" >&2
            exit 1
        }

        # exit venv shell
        kill -SIGUSR1 $VIRTUAL_ENV_SHELL_PID || {
            printf "Failed to kill virtual environment shell
" >&2
            exit 1
        }
        exit 0
    ;;
    *)
        usage >&2
        exit 1
    ;;
esac

解决方案 13:

这是我想出的一个超级黑客方法,但我仍然不满意,哈哈

这适用于 zsh

function cd() {
  # use builtin to use as part of function with same name
  builtin cd $1

  # source env if found
  if [ -f env/bin/activate ]; then
    source env/bin/activate

  # keeps env sourced 1 dir deep
  elif [ -f ./../env/bin/activate ]; then
    source ./../env/bin/activate

  # deactivate when leaving project dir
  elif command -v deactivate &> /dev/null; then
    deactivate
  fi
}
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3930  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2729  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   67  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   74  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   60  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用