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

sunny0 2020-03-03

在学习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\n  eval "$(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 % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   148  100   148    0     0     20      0  0:00:07  0:00:07 --:--:--    39
100  2454  100  2454    0     0     94      0  0:00:26  0: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 functions

alias 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

[ ~]# 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。

  1. 安装编译python需要的依赖包

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

[ ~]# mkdir ~/.pyenv/cache
[ ~]#
[ ~]# cp Python-3.8.2.tar.xz ~/.pyenv/cache/

然后再执行安装命令的时候,它就会自动使用缓存里的源码包,这样安装速度就会比较快。

3. 安装

[ ~]# 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目录下,如下所示:

[ ~]# ls /root/.pyenv/versions/
3.8.2

然后我们再查看已经安装的版本信息,就能够看到新安装的3.8.2,如下所示:

[ ~]# pyenv versions

  • system (set by /root/.pyenv/version)
    3.8.2
  1. 使用

既然模板搭建好了,那么我们现在就可以使用这个模板来创建我们需要的虚拟环境。在创建之前我们需要说几个注意的点:

  • 当前模板中安装了某个包,那么以这个模板创建的虚拟环境中就会有这个包。
  • 虚拟环境创建以后,模板中新安装的包不会出现在虚拟环境中。也就是说虚拟环境一旦创建,虚拟环境和模板就是两个完全隔离的环境了。

下面我们来看一个创建虚拟环境具体的例子,创建虚拟环境的命令基本格式是:

pyenv virtualenv  template_version   virtualenv_name

template_version指的是模板的版本号,virutalenv_name指的是虚拟环境名词,一般是你的项目的名称。假设我们要开发一个cmdb项目,那么我们就来创建一个cmdb的虚拟环境,如下所示:

[ ~]# 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)
[ ~]# 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

示例如下:

[dminnode ~]# mkdir cmdb
[ ~]# ls
anaconda-ks.cfg  cmdb  docker  Python-3.8.2.tar.xz
[ ~]# cd cmdb
[ cmdb]# pyenv local cmdb
(cmdb) [ cmdb]#

在上面的代码中我们可以看到,切换到项目cmdb目录下以后,设置该目录的虚拟环境为cmdb,然后我们从shell的提示符中可以看到,前面多了一个(cmdb)的提示,表示我们进入到虚拟环境了,也就是说这个时候就是一个独立的python开发环境。我们看一下这个目录的内容,如下所示:

(cmdb) [ cmdb]# ls -al 
total 8
drwxr-xr-x. 2 root root   29 Mar  3 11:29 .
dr-xr-x---. 9 root root 4096 Mar  3 11:24 ..
-rw-r--r--. 1 root root    5 Mar  3 11:29 .python-version
(cmdb) [ cmdb]# cat .python-version 
cmdb

可以看到多了一个隐藏文件.python-version,文件内容是cmdb,也就是说pyenv是通过这个文件来控制当前目录下的虚拟环境。

  1. 虚拟环境的删除

当开发项目越来越多以后,可能虚拟环境的信息也会越来越多,因此就需要删除一些不再使用的虚拟环境,这个时候就需要用到删除命令,如下所示:

pyenv virtualenv-delete virtualenv_name

但是删除之前,建议你通过虚拟环境的pip命令导出虚拟环境下的包列表,命令是:

pip freeze --all  > requirements.txt

将已安装的包导出到requirements.txt文件中,然后再删除这个虚拟环境:

(cmdb) [ cmdb]# pyenv virtualenv-delete cmdb
pyenv-virtualenv: remove /root/.pyenv/versions/3.8.2/envs/cmdb? y
[ cmdb]# ls -al 
total 12
drwxr-xr-x. 2 root root   53 Mar  3 11:41 .
dr-xr-x---. 9 root root 4096 Mar  3 11:24 ..
-rw-r--r--. 1 root root    5 Mar  3 11:29 .python-version
-rw-r--r--. 1 root root   31 Mar  3 11:41 requirements.txt
[ cmdb]# cat .python-version 
cmdb

删除完成后,当前目录下的.python-version文件还存在,但是因为找不到对应的虚拟环境信息,此时就无法生效。

以上就是pyenv的配置和使用基本信息,如果对内容比较感兴趣可以留言大家一起讨论。

相关推荐