激活python虚拟环境如何修改sys.path? [英] How does activating a python virtual environment modify sys.path?

查看:168
本文介绍了激活python虚拟环境如何修改sys.path?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下命令创建我的python虚拟环境:

 <代码> python3 -m venv venv3 

要激活,我 source venv3/bin/activate .

venv3/bin/activate 似乎并不那么复杂:

 #此文件必须与源bin/激活"一起使用* from bash *#您不能直接运行它停用(){#重置旧的环境变量如果[-n"$ _OLD_VIRTUAL_PATH"];然后PATH ="$ _ OLD_VIRTUAL_PATH"导出路径未设置_OLD_VIRTUAL_PATH科幻如果[-n"$ _OLD_VIRTUAL_PYTHONHOME"];然后PYTHONHOME ="$ _ OLD_VIRTUAL_PYTHONHOME"导出PYTHONHOME未设置_OLD_VIRTUAL_PYTHONHOME科幻#这应该检测bash和zsh,它们具有必须执行的hash命令#被调用以使其忘记过去的命令.不忘#过去的命令可能不会尊重我们对$ PATH所做的更改如果[-n"$ BASH" -o -n"$ ZSH_VERSION"];然后哈希-r科幻如果[-n"$ _OLD_VIRTUAL_PS1"];然后PS1 ="$ _ OLD_VIRTUAL_PS1"出口PS1未设置_OLD_VIRTUAL_PS1科幻未设置VIRTUAL_ENV如果 [ !"$ 1" =非破坏性"];然后# 自毁!取消设置-f停用科幻}#设置不相关的变量停用非破坏性VIRTUAL_ENV ="/home/pi/django-test/venv3"汇出VIRTUAL_ENV_OLD_VIRTUAL_PATH ="$ PATH"PATH ="$ VIRTUAL_ENV/bin:$ PATH"导出路径#取消设置PYTHONHOME#如果将PYTHONHOME设置为空字符串,则此操作将失败(无论如何都是错误的)#可以在bash中使用`if(set -u;:$ PYTHONHOME);`如果[-n"$ PYTHONHOME"];然后_OLD_VIRTUAL_PYTHONHOME ="$ PYTHONHOME"未设定PYTHONHOME科幻如果[-z"$ VIRTUAL_ENV_DISABLE_PROMPT"];然后_OLD_VIRTUAL_PS1 ="$ PS1"如果["x(venv3)"!= x];然后PS1 =(venv3)$ PS1"别的如果[`basename \" $ VIRTUAL_ENV \`" ="__"];然后#Aspen魔术目录的特殊情况#参见http://www.zetadev.com/software/aspen/PS1 ="[`basename \`dirname \" $ VIRTUAL_ENV \"\"] $ PS1别的PS1 =(`basename \" $ VIRTUAL_ENV \`)$ PS1"科幻科幻出口PS1科幻#这应该检测bash和zsh,它们具有必须执行的hash命令#被调用以使其忘记过去的命令.不忘#过去的命令可能不会尊重我们对$ PATH所做的更改如果[-n"$ BASH" -o -n"$ ZSH_VERSION"];然后哈希-r科幻 

我可以看到它修改了$ 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 ,位于虚拟环境的站点目录下.

如果创建的虚拟环境没有选项-system-site-packages ,则文件名为 no-global-site-packages.txt 将被写入venv的站点目录.

在python启动期间,将执行 site.py ,它将修改版.

希望这可以回答您的问题.

I create my python virtual environment using:

python3 -m venv venv3

to activate, I source venv3/bin/activate.

venv3/bin/activate doesn't appear to be all that complex:

# 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

I can see it modifying $PATH, and $PS1, creating a deactivate function, and even backing up old variables that it modifies so it can restore them when the user runs the deactivate function. All this makes sense.

The one thing I don't see is where python's sys.path is modified. On my system, this is what I see:

sys.path outside of virtual environment:

['', '/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 inside of virtual environment:

['', '/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']

Clearly, sys.path gets modified at some point, somehow. This makes sense, since that's how python knows where to find the third-party python libraries that are installed. I would think that this is the main feature of the virtual environment, but I can't see where it gets set.

I'm not trying to accomplish anything - mostly just curious.

解决方案

sys.path is initiated in site.py, it is set using the relative path of sys.prefix, which is the path of python executable inside the virtual environment.

assuming you are using virtualenv, rather than -m venv, access to system-wide site-packages is controlled with a flag file named no-global-site-packages.txt, under site dir of the virtual environment.

if the virtual environment is created without option --system-site-packages, a file named no-global-site-packages.txt will be written into the site dir of venv.

during python startup, site.py is executed, it will check the existence of no-global-site-packages.txt, if this flag file not exists, system-wide site package path will be added to sys.path, which is infered from sys.real_prefix. site.py in a virtualenv created venv is a modified version.

hope this could answer your question.

这篇关于激活python虚拟环境如何修改sys.path?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆