python|Linux系统Python虚拟环境管理软件pyenv

在学习Python的时候,最经常遇到的问题就是包版本的问题,比如说这个应用需要libtool包的1.1.1版本,而之前开发的应用则只能运行在1.0.1版本上。那么怎么让两个应用都能够正常运行起来呢?聪明的开发者们提出了虚拟环境的概念,就像电脑的虚拟机一样,创建一个虚拟环境就像创建了虚拟机。你在虚拟环境里做任何操作都不会影响到其他的虚拟环境,也不会影响到系统环境。同时你也可以在你的虚拟环境里安装任何版本的包来进行测试。
在昨天的文章里介绍了Python使用的比较多的一个虚拟环境管理包virtualenv,这个包用在windows系统上比较多。而在Linux/Unix系统上用的比较多的是另外一个虚拟环境管理工具pyenv。
什么是pyenv
pyenv是一个虚拟环境管理工具,可以同时管理多个Python版本,并能以这些Python版本为模板来创建不同的虚拟环境,而且可以灵活的在这些虚拟环境之间进行切换。它具有以下优点:

  • 可以直接修改全局Python版本(慎重操作,危险)
  • 每个项目一个Python版本
  • 从多个Python版本中同时搜索命令,方便测试跨版本软件。
既然这么方便,那么我们来看一下它是怎么使用的吧。
安装
目前这个软件还不支持在windows系统上使用,暂时只支持在Linux和Unix上安装。对于macOS,可以使用Homebrew来安装,官方文档上对应的链接是:https://github.com/pyenv/pyenv#homebrew-on-macos
对于Linux/Unix用户来说,有两种安装方式,第一种是根据官方文档来一步步安装,步骤如下:
  1. 克隆安装软件。命令是
    $ git clone https://github.com/pyenv/pyenv.git ~/.pyenv

  2. 定义环境变量
    $ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile $ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile

    对于使用zsh的用户,需要把 ~/.bash_profile改成~/.zshrc
    对于使用Ubuntu的用户,需要把 ~/.bash_profile改成~/.bashrc
  3. 将pyenv init命令添加到shell里已启用shims和自动补全,shims是用于多版本Python选择的工具,添加命令如下:
    $ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\neval "$(pyenv init -)"\nfi' >> ~/.bash_profile

    对于使用zsh的用户,需要把 ~/.bash_profile改成~/.zshrc
    对于使用Ubuntu的用户,需要把 ~/.bash_profile改成~/.bashrc
  4. 重启shell让配置的命令生效,可以退出shell重新登录,也可以执行命令:
    $ exec "$SHELL"

上面的安装步骤看起来非常繁琐对吧,官方也因此提供了一个一键安装脚本,通过这个一键安装脚本,上面的3个步骤都可以省略了,安装脚本的命令是:
$ curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash

注意:需要提前安装好git,因为它也是先通过git克隆到本地。
脚本执行过程如下:
% Total% Received % XferdAverage SpeedTimeTimeTimeCurrent DloadUploadTotalSpentLeftSpeed 100148100148002000:00:070:00:07 --:--:--39 10024541002454009400:00:260:00:26 --:--:--668 Cloning into '/root/.pyenv'... remote: Enumerating objects: 670, done. remote: Counting objects: 100% (670/670), done. remote: Compressing objects: 100% (503/503), done. remote: Total 670 (delta 335), reused 255 (delta 76), pack-reused 0 Receiving objects: 100% (670/670), 380.59 KiB | 30.00 KiB/s, done. Resolving deltas: 100% (335/335), done. .... Cloning into '/root/.pyenv/plugins/pyenv-which-ext'... remote: Enumerating objects: 10, done. remote: Counting objects: 100% (10/10), done. remote: Compressing objects: 100% (6/6), done. remote: Total 10 (delta 1), reused 6 (delta 0), pack-reused 0 Unpacking objects: 100% (10/10), done.

这中间会克隆多个包,输出信息比较长,内容类似,所以这里省略了一部分。脚本执行完毕以后,会提示你,没有把pyenv添加到PATH路径,然后你根据它的提示添加一下。提示内容如下所示:
WARNING: seems you still have not added 'pyenv' to the load path.# Load pyenv automatically by adding # the following to ~/.bashrc:export PATH="/root/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"

我们需要执行的操作是,打开~/.bashrc文件,把最下面三行添加进去,添加好的~/.bashrc文件如下所示:
# .bashrc# User specific aliases and functionsalias rm='rm -i' alias cp='cp -i' alias mv='mv -i'# Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi export PATH="/root/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"

保存退出,然后执行一下命令:
source ~/.bashrc

让配置生效。
使用
到这里,pyenv就已经安装好了。然后我们执行命令pyenv versions
[root@adminnode ~]# pyenv versions * system (set by /root/.pyenv/version)

这个命令不是查看pyenv的版本的,而是查看当前系统上安装了哪几个版本的Python,正常情况下刚安装好只有一个system,对应的是系统的python版本。例如CentOS7默认是python2.7,而CentOS 8现在默认是python3.6。
因此如果我们想使用其他版本的python作为虚拟环境的模板时,就需要自己来安装对应的版本,比如现在Python的最新版本已经到了3.8.2版本,我希望以这个版本来作为模板。那么我就需要安装3.8.2。
安装编译python需要的依赖包
yum install -y gcc make patch gdbm-devel openssl-devel sqlite-devel \ readline-devel zlib-devel bzip2-devellibffi-devel

下载python源码包 这一步如果是在国内的服务器或虚拟机上建议操作,因为我们自己不下载的话,pyenv它默认会到python.org的官网上去下载源码包,因为不同地区的网络环境不一样,可能会导致这一步特别慢,甚至会直接失败。因此我们推荐首先自己到python官网下载好源码包。然后上传到你的服务器上,然后拷贝到pyenv的缓存目录中,如下所示:
[root@adminnode ~]# ls anaconda-ks.cfgPython-3.8.2.tar.xz [root@adminnode ~]# mkdir ~/.pyenv/cache [root@adminnode ~]# [root@adminnode ~]# cp Python-3.8.2.tar.xz ~/.pyenv/cache/

然后再执行安装命令的时候,它就会自动使用缓存里的源码包,这样安装速度就会比较快。
安装
[root@adminnode ~]# pyenv install 3.8.2 Installing Python-3.8.2... Installed Python-3.8.2 to /root/.pyenv/versions/3.8.2

耐心等待它安装完成,这里安装命令后面直接跟上python对应的版本号即可。安装完成后,所有版本的python都是安装在/root/.pyenv/versions目录下,如下所示:
[root@adminnode ~]# ls /root/.pyenv/versions/ 3.8.2

然后我们再查看已经安装的版本信息,就能够看到新安装的3.8.2,如下所示:
[root@adminnode ~]# pyenv versions * system (set by /root/.pyenv/version) 3.8.2

使用 既然模板搭建好了,那么我们现在就可以使用这个模板来创建我们需要的虚拟环境。在创建之前我们需要说几个注意的点:
  • 当前模板中安装了某个包,那么以这个模板创建的虚拟环境中就会有这个包。
  • 虚拟环境创建以后,模板中新安装的包不会出现在虚拟环境中。也就是说虚拟环境一旦创建,虚拟环境和模板就是两个完全隔离的环境了。
下面我们来看一个创建虚拟环境具体的例子,创建虚拟环境的命令基本格式是:
pyenv virtualenvtemplate_versionvirtualenv_name

template_version指的是模板的版本号,virutalenv_name指的是虚拟环境名词,一般是你的项目的名称。假设我们要开发一个cmdb项目,那么我们就来创建一个cmdb的虚拟环境,如下所示:
[root@adminnode ~]# pyenv virtualenv 3.8.2 cmdb Looking in links: /tmp/tmp_42mjdiv Requirement already satisfied: setuptools in /root/.pyenv/versions/3.8.2/envs/cmdb/lib/python3.8/site-packages (41.2.0) Requirement already satisfied: pip in /root/.pyenv/versions/3.8.2/envs/cmdb/lib/python3.8/site-packages (19.2.3) [root@adminnode ~]# pyenv versions * system (set by /root/.pyenv/version) 3.8.2 3.8.2/envs/cmdb cmdb

这个时候就能看到创建好的虚拟环境名称,但是也可以看到当前目录下的python版本还是system,那么怎么切换到cmdb版本呢?
pyenv是以目录为单位来进行版本控制的,比如说你单独一个项目有一个项目目录,我在项目目录下设置好这个项目的python版本,那么项目的子目录全部会自动继承这个配置。设置目录的python版本命令是:
pyenv local virtualenv_name

示例如下:
[root@adminnode ~]# mkdir cmdb [root@adminnode ~]# ls anaconda-ks.cfgcmdbdockerPython-3.8.2.tar.xz [root@adminnode ~]# cd cmdb [root@adminnode cmdb]# pyenv local cmdb (cmdb) [root@adminnode cmdb]#

在上面的代码中我们可以看到,切换到项目cmdb目录下以后,设置该目录的虚拟环境为cmdb,然后我们从shell的提示符中可以看到,前面多了一个(cmdb)的提示,表示我们进入到虚拟环境了,也就是说这个时候就是一个独立的python开发环境。我们看一下这个目录的内容,如下所示:
(cmdb) [root@adminnode cmdb]# ls -al total 8 drwxr-xr-x. 2 root root29 Mar3 11:29 . dr-xr-x---. 9 root root 4096 Mar3 11:24 .. -rw-r--r--. 1 root root5 Mar3 11:29 .python-version (cmdb) [root@adminnode cmdb]# cat .python-version cmdb

可以看到多了一个隐藏文件.python-version,文件内容是cmdb,也就是说pyenv是通过这个文件来控制当前目录下的虚拟环境。
  1. 虚拟环境的删除
当开发项目越来越多以后,可能虚拟环境的信息也会越来越多,因此就需要删除一些不再使用的虚拟环境,这个时候就需要用到删除命令,如下所示:
pyenv virtualenv-delete virtualenv_name

但是删除之前,建议你通过虚拟环境的pip命令导出虚拟环境下的包列表,命令是:
pip freeze --all> requirements.txt

将已安装的包导出到requirements.txt文件中,然后再删除这个虚拟环境:
(cmdb) [root@adminnode cmdb]# pyenv virtualenv-delete cmdb pyenv-virtualenv: remove /root/.pyenv/versions/3.8.2/envs/cmdb? y [root@adminnode cmdb]# ls -al total 12 drwxr-xr-x. 2 root root53 Mar3 11:41 . dr-xr-x---. 9 root root 4096 Mar3 11:24 .. -rw-r--r--. 1 root root5 Mar3 11:29 .python-version -rw-r--r--. 1 root root31 Mar3 11:41 requirements.txt [root@adminnode cmdb]# cat .python-version cmdb

删除完成后,当前目录下的.python-version文件还存在,但是因为找不到对应的虚拟环境信息,此时就无法生效。
【python|Linux系统Python虚拟环境管理软件pyenv】以上就是pyenv的配置和使用基本信息,如果对内容比较感兴趣可以留言大家一起讨论。

    推荐阅读