一、virtualenv
Python 的背后有着庞大的开源社区支持,但是有一个缺点就是每个包的质量都参差不齐,如果我们在工作服务器上去测试安装每个包,就会造成整个的服务器形成庞大复杂的第三方包依赖。virtualenv 是一个 Python 环境配置和切换的工具,可以用它配置多个 Python 运行环境,和系统中的 Python 环境隔离,即所谓的沙盒。使用沙盒的好处,包括:
- 解决库之间的版本依赖,比如同一系统上不同应用依赖同一个库的不同版本。
- 解决权限限制,比如你没有 root 权限。
- 尝试新的工具,而不用担心污染系统环境。
首先,我们用pip
安装 virtualenv:
1 |
$ pip3 install virtualenv |
然后,假定我们要开发一个新的项目,需要一套独立的 Python 运行环境,可以这么做,先创建项目目录:
1 2 |
$ mkdir myproject $ cd myproject/ |
创建一个独立的 Python 运行环境为 myproject 项目,命名为 test:
1 2 3 |
$ virtualenv --no-site-packages test New python executable in /root/test/bin/python Installing setuptools, pip, wheel...done. |
命令virtualenv
就可以创建一个独立的 Python 运行环境,我们还加上了参数--no-site-packages
,这样,已经安装到系统 Python 环境中的所有第三方包都不会复制过来,这样,我们就得到了一个不带任何第三方包的“干净”的 Python 运行环境。
新建的 Python 环境被放到当前目录下的 test 目录。有了 test 这个 Python 环境,可以用source
进入该环境:
1 2 3 |
$ source ./test/bin/activate (test)[root@localhost ~]# which python3.6 /root/test/bin/python3.6 |
注意到命令提示符变了,有个(test)前缀,表示当前环境是一个名为 test 的 Python 环境。
下面正常安装各种第三方包:
1 |
(test)[root@localhost ~]# pip install django |
在 test 环境下,用 pip 安装的包都被安装到 test 这个环境下,系统 Python 环境不受任何影响。也就是说,test 环境是专门针对 myproject 这个应用创建的。
退出当前的 test 环境,使用deactivate命令:
1 2 3 |
(test)[root@localhost ~]# deactivate [root@localhost ~]# which python3.6 /usr/local/bin/python3.6 |
使用 virtualenv 可以创建多个项目,然后在每个项目运行不同的应用环境,它们相互之间并无干扰。
virtualenv 是如何创建“独立”的 Python 运行环境的呢?原理很简单,就是把系统 Python 复制一份到 virtualenv 的环境,用命令source test/bin/activate
进入一个 virtualenv 环境时,virtualenv 会修改相关环境变量,让命令python
和pip
均指向当前的 virtualenv 环境。
二、virtualenvwrapper
“wrapper” 的中文意思是包装,由此看出,virtualenvwrapper 就是对 virtualenv 的一个包装。我们在使用 virtualenv 时可以看出,virtualenv 的一个最大的缺点就是,每次开启虚拟环境之前要去虚拟环境所在目录下的 bin 目录下 source 一下 activate,这就需要我们记住每个虚拟环境所在的目录。它没有帮我们整合从而快速切入,一种可行的解决方案是,将所有的虚拟环境目录全都集中起来,比如放到 ~/virtualenvs/,并对不同的虚拟环境使用不同的目录来管理。这就是 virtualenvwrapper 诞生的原因。并且,它还省去了每次开启虚拟环境时候的 source 操作,使得虚拟环境更加好用。
在 Python3 下安装 virtualenvwrapper 也很简单,直接使用 pip 即可。
1 |
$ pip install virtualenvwrapper |
安装成功后,首先需要对 virtualenvwrapper 进行配置。它需要指定一个环境变量,叫做 WORKON_HOME,用来设置存放 virtualenv 的统一管理目录。并且需要运行一下它的初始化工具 virtualenvwrapper.sh,这个脚本在对应 Python 版本的 bin 目录下。
由于每次都需要执行这两部操作,我们可以将其写入终端的配置文件中。例如,如果使用 bash,则添加到 ~/.bashrc 中;如果使用 zsh,则添加到 ~/.zshrc 中。这样每次启动终端的时候都会自动运行。
1 2 3 4 |
export WORKON_HOME=~/.virtualenvs export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--no-site-packages' export VIRTUALENVWRAPPER_PYTHON=/root/.pyenv/versions/3.6.4/bin/python3.6 source /root/.pyenv/versions/3.6.4/bin/virtualenvwrapper.sh |
变量 VIRTUALENVWRAPPER_VIRTUALENV_ARGS 用来给定生成独立运行环境时的参数,加上参数--no-site-packages
,表示已经安装到系统 Python 环境中的所有第三方包都不会复制过来,这样,我们就得到了一个不带任何第三方包的“干净”的 Python 运行环境。
变量 VIRTUALENVWRAPPER_PYTHON 可以用来指定运行的 Python 版本,可选。
都完成之后,就可以 source .bashrc 一下,然后就可以使用 virtualenvwarpper 了。
首先,可以使用 mkvirtualenv 创建一个虚拟环境,如下。
1 |
$ mkvirtualenv flask |
之后我们就有了一个叫做 flask 的虚拟环境,它被存放在 $WORKON_HOME/flask 目录下。
新建虚拟环境之后会自动激活虚拟环境。如果我们平时想要进入某个虚拟环境,可以用下面的命令。
1 |
$ workon flask |
这也就是为什么环境变量中存放虚拟环境的目录为啥叫做 WORKON_HOME。顺便说一句,workon 后面可是可以支持用 tab 自动补全的哟。
当我们想查看我有多少个虚拟环境时,就可以使用 lsvirtualenv 命令了,它会帮我们列出我们使用 mkvirtualenv 命令创建的所有虚拟环境。
1 |
$ lsvirtualenv |
同样,离开虚拟环境,可以使用。
1 |
$ deactivate |
另外,当我们删除一个虚拟环境时,也很简单。
1 |
$ rmvirtualenv flask |
当我们 workon 到某个虚拟环境后,比如你想进入到虚拟环境的 site-packages 目录,可以使用 cdsitepackages 命令。如果只是想浏览 site-packages 目录,可以直接使用 lssitepackages 命令。想回到当前虚拟环境根目录,可以使用 cdvirtualenv 命令。基本常用命令就这么多了。
三、pyenv
pyenv 对比 virtualenv 工具来说,解决的问题不同。virtualenv 是一个沙盒,避免环境污染的,而 pyenv 是一个 Python 版本管理器,用来在同一个系统上切换不同的 Python 解释器的,并且 pyenv 是使用 shell 写的,所以容易阅读。经常遇到这样的情况:
- 系统自带的 Python 是 2.6,自己需要 Python 2.7 中的某些特性;
- 系统自带的 Python 是 2.x,自己需要 Python 3.x;
此时需要在系统中安装多个 Python,但又不能影响系统自带的 Python,即需要实现 Python 的多版本共存。pyenv 就是这样一个 Python 版本管理器。
1. 安装Pyenv
在终端执行如下命令以安装pyenv及其插件(安装 pyenv 全家桶):
1 |
$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash |
内容除了包含 pyenv 以外,还包含如下插件(在 $HOME/.pyenv/plugins 目录下存放):
- pyenv-doctor
- pyenv-installer
- pyenv-update
- pyenv-virtualenv
- pyenv-which-ext
默认会安装在当前用户家目录下。安装完成后,根据提示将如下语句加入到 ~/.bash_profile
中:
1 2 3 4 |
export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" |
然后重启终端即可。
1 2 |
$ pyenv -v pyenv 1.2.3 |
2. 查看Python可安装版本
查看可安装的版本(pyenv 仅支持此范围内版本安装,如果想扩展可以自行修改 pyenv 代码)
1 |
$ pyenv install --list |
该命令会列出可以用 pyenv 安装的 Python 版本。列表很长,仅列举其中几个:
1 2 3 4 |
2.7.14 #Python 2最新版本; 3.6.5 #Python 3最新版本; anaconda2-5.1.0 #支持Python 2.6和2.7; anaconda3-5.1.0 #支持Python 3.3和3.4; |
其中 2.7.14 和 3.6.5 这种只有版本号的是 Python 官方版本,其他的形如 anaconda3-5.1.0 这种既有名称又有版本后的属于 “衍生版” 或发行版。还有如:ironpython、jython、pypy、pyston 等。
3. 安装Python的依赖包
在编译 Python 过程中会依赖一些其他库文件,因而需要首先安装这些库文件,已知的一些需要预先安装的库如下。
在 CentOS/RHEL/Fedora 下:
1 |
$ sudo yum install readline readline-devel readline-static openssl openssl-devel openssl-static sqlite-devel python-devel patch gcc |
在 Ubuntu 下:
1 2 3 |
$ sudo apt-get update $ sudo apt-get install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl $ sudo apt-get install llvm libncurses5-dev libncursesw5-dev |
4. 安装指定版本
用户可以使用pyenv install
安装指定版本的 Python。如果是做科学计算的话,推荐你安装 anaconda3 的最新版本,这是一个专门为科学计算准备的发行版。
1 2 3 |
$ pyenv install 3.6.4 -v Downloading Python-3.6.4.tar.xz... -> https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tar.xz |
执行该命令后,会从给定的网址中下载安装文件 Python-3.6.4.tar.xz。但由于文件很大,通常下载需要很久。建议的做法是,先执行以上命令然后马上中断安装,这样就知道pyenv要下载的文件的链接。然后用户自己用其他更快的方式(比如wget、迅雷等等)从该链接中下载安装文件,并将安装文件移动到 ~/.pyenv/cache
目录下(该目录默认不存在,用户要自行新建)。 然后重新执行pyenv install 3.6.4 -v
命令。该命令会检查 cache 目录下已有文件的完整性,若确认无误,则会直接使用该安装文件进行安装。
安装过程中,若出现编译错误,通常是由于依赖包未满足,需要在安装依赖包后重新执行该命令。
5. 更新数据库
在安装 Python 或者其他带有可执行文件的模块之后,需要对数据库进行更新:
1 |
$ pyenv rehash |
查看当前已安装的 Python 版本
1 2 3 |
$ pyenv versions * system (set by /root/.pyenv/version) 3.6.4 |
其中的星号表示当前正在使用的是系统自带的 Python。
6. 设置Python执行环境
pyenv 可以从三个维度来管理 Python 环境,简称为:当前系统、当前目录、当前 shell。这三个维度的优先级从左到右依次升高,即当前系统的优先级最低、当前shell的优先级最高。
如果想修改系统全局的 Python 环境,可以采用 pyenv global PYTHON_VERSION 命令。该命令执行后会在 $(pyenv root) 目录(默认为~/.pyenv)中创建一个名为 version 的文件(如果该文件已存在,则修改该文件的内容),里面记录着系统全局的 Python 版本号。但是最好不要这么使用,可能会影响系统或其他运行环境。
所以,一般都是通过 pyenv local PYTHON_VERSION 命令来修改当前目录的 Python 环境。命令执行后,会在当前目录中生成一个 .python-version 文件(如果该文件已存在,则修改该文件的内容),里面记录着当前目录使用的 Python 版本号。如下:
1 2 3 4 |
$ pyenv local 3.6.4 $ pyenv versions system * 3.6.4 (set by /root/.python-version) |
其中,输出结果前面的 “*” 表示当前正在使用的版本。查看环境变量,会发现当前目录中的 .python-version 配置优先于系统全局的 ~/.pyenv/version 配置。
另外一种情况,通过执行 pyenv shell PYTHON_VERSION 命令,可以修改当前 shell 的 Python 环境。执行该命令后,会在当前 shell session(Terminal窗口)中创建一个名为 PYENV_VERSION 的环境变量,然后在当前 shell 的任意目录中都会采用该环境变量设定的 Python 版本。此时,当前系统和当前目录中设定的 Python 版本均会被忽略。
7. 确认Python版本
由于我们使用的是当前目录运行模式,所以在当前目录及子目录进入 Python 交互模式就可以看到新版本生效了。
1 2 3 4 5 |
$ python Python 3.6.4 (default, Apr 22 2018, 22:19:15) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> |
如果在父目录运行则会进入系统自带 Python 环境。
8. 使用pyenv-virtualenv进行环境隔离
经过以上操作,我们在本地计算机中就可以安装多个版本的 Python 运行环境,并可以按照实际需求进行灵活地切换。然而,很多时候在同一个 Python 版本下,我们仍然希望能根据项目进行环境分离,就跟之前我们使用 virtualenv 一样。
在 pyenv 中,也包含这么一个插件,pyenv-virtualenv,可以实现同样的功能。使用方式如下:
1 |
$ pyenv virtualenv PYTHON_VERSION PROJECT_NAME |
其中,PYTHON_VERSION 是具体的 Python 版本号,例如,3.6.4,PROJECT_NAME 是我们自定义的项目名称。比较好的实践方式是,在 PROJECT_NAME 也带上 Python 的版本号,以便于识别。
现假设我们有 mysite 这么一个项目,想针对 Python 2.7.13 和 Python 3.6.4 分别创建一个虚拟环境,那就可以依次执行如下命令(前提是相关 Python 版本包在 pyenv 中已经安装完毕)。
1 2 |
$ pyenv virtualenv 3.6.4 py36_mysite $ pyenv virtualenv 2.7.13 py27_mysite |
创建完成后,通过执行 pyenv virtualenvs 命令,就可以看到本地所有的项目环境。
1 2 3 |
$ pyenv virtualenvs 3.6.4/envs/py36_mysite (created from /Users/dkey/.pyenv/versions/3.6.4) py36_mysite (created from /Users/dkey/.pyenv/versions/3.6.4) |
创建完工作环境以后,可以通过 activate 和 deactivate 子命令进入或退出一个工作环境。进入工作环境以后,左边的提示符会显示你当前所在的工作环境,以免因为环境太多导致误操作。
1 2 |
$ pyenv activate py36_mysite (py36_mysite) MacBook-Air:~ dkey$ |
接下来,就可以在不同的工作环境使用 pip 安装不同的包版本了。
如果想要删除虚拟环境,则使用:
1 2 |
$ pyenv virtualenv-delete py36_mysite $ pyenv uninstall py36_mysite |
使用 pyenv 和 python-virtualenv 插件,我们就能够自由地在不同的版本之间进行切换,相比管理 Python 版本,不但节省了时间,也避免了工作过程中的相互干扰。以上便是日常开发工作中常用的 pyenv 命令,基本可以满足绝大多数依赖库环境管理方面的需求。
9. 其他常用功能
pyenv commands
:查看 pyenv 支持的所有命令。
pyenv uninstall
:卸载某个版本或移除某个项目。
pyenv update
:更新 pyenv 及其插件。
Tips:
- 输入
python
即可使用新版本的 Python;- 系统自带的脚本会以
/usr/bin/python
的方式直接调用老版本的 Python,因而不会对系统脚本产生影响;- 使用
pip
安装第三方模块时会自动按照到当前的 Python 版本下,不会和系统模块发生冲突。- 使用
pip
安装模块后,可能需要执行pyenv rehash
更新数据库;
<参考>
https://www.liaoxuefeng.com/wiki/1016959663602400/1019273143120480