龙空技术网

Python虚拟环境详解

孤狼游戏开发 325

前言:

现时我们对“python虚拟环境原理”大致比较看重,看官们都想要了解一些“python虚拟环境原理”的相关内容。那么小编也在网络上汇集了一些关于“python虚拟环境原理””的相关知识,希望朋友们能喜欢,姐妹们快快来了解一下吧!

和其他大多数现代编程语言一样,Python对包和模块的下载、存储以及管理有其自己的一套方法。Python的包一般存在几个地方。比如,大部分系统包会存在sys.prefix指定的路径下。在Mac OS X下这个路径为:

>>> import sys

>>> sys.prefix

'/System/Library/Frameworks/Python.framework/Versions/3.5'

通常情况下我们更关心第三方包的安装位置,比如easy_install或pip会将包存放在 site.getsitepackages所指定的路径下:

>>> import site

>>> site.getsitepackages()

[

'/System/Library/Frameworks/Python.framework/Versions/3.5/Extras/lib/python',

'/Library/Python/3.5/site-packages'

]

这里就带来了一个问题,当我们同时开发多个工程时,不同的工程会将第三方的包存放在相同的路径下。这就意味着,如果有两个工程依赖同一个包,但是所需要的版本却不一样,比如工程A依赖v1.0.0,而工程B依赖v2.0.0。由于Python无法根据版本来区分包的安装路径,所以这里就会发生版本冲突。这也就是本文所要介绍的虚拟环境(virtualenv/venv)所要解决的问题。

什么是虚拟环境?

Python虚拟环境的主要目的是为了给不同的工程创建互相独立的运行环境。在虚拟环境下,每一个工程都有自己的依赖包,而与其它的工程无关。不同的虚拟环境中同一个包可以有不同的版本。并且,虚拟环境的数量没有限制,我们可以轻松地用virtualenv或者pyenv等工具来创建多个虚拟环境。

虚拟环境的使用

安装虚拟环境工具的方法非常简单,

$ pip install virtualenv

然后,我们创建一个名字叫“env”的虚拟环境:

$ virtualenv env

这条命令会自动创建一个叫“env”的目录,并在其中生成如下的目录结构:

├── bin

│ ├── activate

│ ├── activate.csh

│ ├── activate.fish

│ ├── easy_install

│ ├── easy_install-3.5

│ ├── pip

│ ├── pip3

│ ├── pip3.5

│ ├── python -> python3.5

│ ├── python3 -> python3.5

│ └── python3.5 -> /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5

├── include

├── lib

│ └── python3.5

│ └── site-packages

└── pyvenv.cfg

这些目录包括:

bin: 用于管理虚拟环境的文件include: 编译Python包时所需要的C头文件lib: Python自带及第三方的库

这其中还包含有一些Python的工具和可执行文件等副本。这些文件用来保证Python代码可以独立于系统环境而运行。

bin目录下有一个重要的脚本文件activate,这个脚本就是用来将其所在的虚拟环境设置为当前Python的运行环境:

$ source env/bin/activate

(env) $

可以看到,在运行完这行命令后,shell的提示符前会出现虚拟环境的名字,表示我们已经进入了这个环境中。

为了验证这一点,我们以bcrypt模块为例。首先我们要在全局系统环境中安装这个模块。在测试之前,我们需要先通过deactivate命令退出当前的虚拟环境:

(env) $ deactivate

$

现在我们的shell提示符回归到了正常状态,同时Python的环境也切换到了全局的系统环境。

现在我们来安装bcrypt并用它来生成一个密码的hash值:

$ pip -q install bcrypt

$ python -c "import bcrypt; print(bcrypt.hashpw('password'.encode('utf-8'), bcrypt.gensalt()))"

$2b$12$vWa/VSvxxyQ9d.WGgVTdrell515Ctux36LCga8nM5QTW0.4w8TXXi

然后我们切换到虚拟环境并试图运行同样的命令:

$ source env/bin/activate

(env) $ python -c "import bcrypt; print(bcrypt.hashpw('password'.encode('utf-8'), bcrypt.gensalt()))"

Traceback (most recent call last):

File "<string>", line 1, in <module>

ImportError: No module named 'bcrypt'

可以看到,在虚拟环境中,bcrypt并没有被安装,说明虚拟环境的隔离作用是生效的。

虚拟环境是如何工作的?

了解虚拟环境背后的工作原理,对于一个Python开发者来说非常重要,它能够帮助我们理解Python的运行环境,对依赖的解析等技术。为了解释虚拟环境的原理,我们先来看一下在不同的环境中,Python可执行文件的位置有什么不同。在默认的系统环境中查看python的路径:

$ which python

/usr/bin/python

然后我们进入虚拟环境

$ source env/bin/activate

(env) $ which python

/Users/michaelherman/python-virtual-environments/env/bin/python

可以看到,在激活虚拟环境后,python可执行文件的路径变成了当前环境目录下的路径,并且$PATH也发生了变化:

$ echo $PATH

/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:

$ source env/bin/activate

(env) $ echo $PATH

/Users/michaelherman/python-virtual-environments/env/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:

虚拟环境下的bin目录排在了$PATH的最前面。这意味着,用户在命令行中执行python的时候,将率先使用虚拟环境下的可执行文件,而不是系统默认的。

那么虚拟环境下的python可执行文件与系统默认的有什么不同呢?Python又是如何找到虚拟环境下的第三方库的呢?

事实上,上面提到的python可执行文件之间并没有什么不同,但是它们所在的位置至关重要。在Python启动的时候,它会获取自身所在的路径。然后这一路径(bin的上一级)被设置到sys.prefix和sys.exec_prefix之中。在搜索第三方的site-packages时,搜索目录是sys.prefix所指向的路径下的lib/pythonX.X/site-packages/,其中X.X是Python的版本。

在前面的例子中,python文件所在路径为/Users/michaelherman/python-virtual-environments/env/bin,因此sys.prefix会被设为/Users/michaelherman/python-virtual-environments/env,从而site-packages的路径就变成了/Users/michaelherman/python-virtual-environments/env/lib/pythonX.X/site-packages。最后,这一路径被存储在sys.path数组中,其中包含着所有包的引用来源。

使用virtualenvwrapper管理虚拟环境

虚拟环境的引入解决了我们关于环境冲突的问题,但是它同时也带来了一个问题,就是虚拟环境过多所带来的管理问题。virtualenvwrapper就是专门用来解决虚拟环境管理问题的一个工具。我们可以很方便地用它来实现对虚拟环境的创建,删除,拷贝,并且可以轻松地在不同环境间进行切换。

virtualenvwrapper的安装非常简单:

$ pip install virtualenvwrapper

安装后,我们需要将virtualenvwrapper.sh脚本添加到shell启动文件中:

$ which virtualenvwrapper.sh

/usr/local/bin/virtualenvwrapper.sh

在shell启动文件~/.bashrc中添加:

export WORKON_HOME=$HOME/.virtualenvs # Optional

export PROJECT_HOME=$HOME/projects # Optional

source /usr/local/bin/virtualenvwrapper.sh

并运行

$ source ~/.bashrc

然后就会在$WORKON_HOME所在的路径下创建集中存放虚拟环境的目录。

接着,我们就可以用下面的一系列命令虚拟环境进行管理:

workon

deactivate

mkvirtualenv

cdvirtualenv

rmvirtualenv

比如,我们要创建一个新的工程:

$ mkvirtualenv my-new-project

(my-new-project) $

此时会在$WORKON_HOME下创建一个新的虚拟环境。

退出一个虚拟环境的方法和之前一样:

(my-new-project) $ deactivate

$

如果你有多个虚拟环境,可以对它们进行查看:

$ workon

my-new-project

my-django-project

web-scraper

并选择其中一个进行激活:

$ workon web-scraper

(web-scraper) $

这样,你就不再需要记住每一个环境存放的具体位置,可以轻松的对他们进行删除、拷贝、切换,是不是非常方便?

好了,关于虚拟环境的介绍就到这里,获取更多精彩内容敬请关注。

标签: #python虚拟环境原理