Virtualenv 是如何被激活的?

萌新Virtualenv 是如何被激活的呀?

休闲玩家:没看过bin目录下的activate文件?

高端玩家activate文件就是个shell脚本。

将函数导入 Shell

source命令可以读取并执行指定文件中的命令(在当前shell环境中),别名是.号。

  1. cat命令在add.sh文件中写入一个“求两数之和”的函数add

  2. cat命令查看add.sh文件的内容;

  3. source命令从add.sh文件中导出add函数;

  4. type命令查看add的类型;

  5. add函数求“二加二”的和。

cat > add.sh << EOF
#! /bin/bash

add () {
    echo \$[ \$1 + \$2 ]
}
EOF

cat add.sh
source add.sh
type add
add 2 2

阅读源码

Virtualenv创建一个虚拟环境目录venv,查看其中bin目录下的activate文件。

virtualenv venv
source venv/bin/activate
vi venv/bin/activate

activate文件开头定义了一个名为deactivate的函数,暂且先跳过它。接着,设置全局环境变量VIRTUAL_ENV,其值为虚拟环境目录的名字(当前为venv)。

VIRTUAL_ENV="/home/pi/venv"
export VIRTUAL_ENV

用变量_OLD_VIRTUAL_PATH维持当前搜索路径$PATH的值。因为虚拟环境的bin目录下有指向Python解释器的符号链接和其它可执行文件,所以将其追加到$PATH中,并导出。

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

Python解释器维持着一个环境变量$PYTHONHOME,用命令$python --help | more查看它的描述——作为sys.prefixsys.exec_prefix的备用前缀目录,会影响模块搜索路径sys.path

if ! [ -z "${PYTHONHOME+_}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
    unset PYTHONHOME
fi

环境变量$PS1持有主命令行提示符字符串,用basename命令获取虚拟环境目录的名字后,修改$PS1并导出。

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1-}"
    if [ "x" != x ] ; then
        PS1="${PS1-}"
    else
        PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}"
    fi
    export PS1
fi

函数deactivate用于还原修改过的环境变量,在命令行中调用就行。

deactivate () {
    unset -f pydoc >/dev/null 2>&1

    # reset old environment variables
    # ! [ -z ${VAR+_} ] returns true if VAR is declared at all
    if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then
        PATH="$_OLD_VIRTUAL_PATH"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if ! [ -z "${_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-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
        hash -r 2>/dev/null
    fi

    if ! [ -z "${_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
}