Joh*_*ohn 12 python bash python-venv
我使用以下方法创建了我的 python 虚拟环境:
python3 -m venv venv3
激活,我source venv3/bin/activate。
venv3/bin/activate 似乎没有那么复杂:
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
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
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/pi/django-test/venv3"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "$PYTHONHOME" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
    unset PYTHONHOME
fi
if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then
    _OLD_VIRTUAL_PS1="$PS1"
    if [ "x(venv3) " != x ] ; then
    PS1="(venv3) $PS1"
    else
    if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
        # special case for Aspen magic directories
        # see http://www.zetadev.com/software/aspen/
        PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
    else
        PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
    fi
    fi
    export PS1
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
我可以看到它修改了 $PATH 和 $PS1,创建了一个deactivate函数,甚至备份了它修改的旧变量,以便在用户运行该deactivate函数时可以恢复它们。这一切都是有道理的。
我没有看到的一件事是修改了 python 的 sys.path 。在我的系统上,这是我看到的:
虚拟环境之外的 sys.path:
['', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-arm-linux-gnueabihf', '/usr/lib/python3.5/lib-dynload', '/usr/local/lib/python3.5/dist-packages', '/usr/lib/python3/dist-packages']
虚拟环境中的 sys.path :
['', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-arm-linux-gnueabihf', '/usr/lib/python3.5/lib-dynload', '/home/pi/django-test/venv3/lib/python3.5/site-packages']
很明显, sys.path 在某个时候被修改了,不知何故。这是有道理的,因为这就是 python 知道在哪里可以找到已安装的第三方 python 库的方式。我认为这是虚拟环境的主要功能,但我看不到它在哪里设置。
我不是想完成任何事情——主要是好奇。
sys.path在 中启动site.py,使用 的相对路径设置sys.prefix,即虚拟环境中python可执行文件的路径。
假设您使用的是virtualenv,而不是-m venv,对系统范围站点包的访问no-global-site-packages.txt由位于虚拟环境站点目录下的名为 的标志文件控制。
如果创建的虚拟环境没有option --system-site-packages,一个名为的文件no-global-site-packages.txt 将被写入sitevenv的目录中。
蟒启动期间,site.py被执行时,它会检查是否存在的no-global-site-packages.txt,如果此标志文件中未存在,全系统的现场包路径将被添加到sys.path,这是从infered sys.real_prefix。site.py
在 virtualenv 创建的 venv 是一个修改版本。
希望这可以回答你的问题。
简短的回答是,激活虚拟环境并没有改变sys.path。sys.path一旦 Python 启动就确定;请参阅https://docs.python.org/3.7/library/sys.html#sys.path。通过调整您的PATH环境变量,虚拟环境所做的就是改变解释器在您简单地运行时实际运行的内容python。