pyenv 和 pyenv-virtualenv 的安装、配置和使用

pyenv 是一个 python 版本管理工具,可以方便的在工作环境中安装、管理和切换不同版本的 python,结合 pyenv-virtualenv 插件,能够方便的创建和管理 python 虚拟环境,在虚拟环境中的各种操作,并不会影响到系统的正常运行,有效防止乱装 python 版本导致系统崩溃等问题的发生。
本文结合自己相关实践,总结了 pyenv 的安装,以及使用 pyenv 安装、管理不同版本的 python 等过程的相关经验,希望对读者有所帮助,本文也借鉴了一些相关的博客、文档等资料,在文中都有列出。
本文相关内容是在已经安装了 Mac os 包管理器 Homebrew 的基础上完成的,系统版本 10.14.5,Linux 系统也可以借鉴,很多设置是相似的,pyenv 命令的使用也是一样的。在进行相关操作前,可以使用 brew update 命令将 Homebrew 升级到最新版本,然后使用 brew upgrade 命令将之前安装过的软件包更新。

pyenv

pyenv 的安装

安装 pyenv 有两种方式:使用 Homebrew 安装和从 Github 克隆,两种方式都比较简便,只需要一点设置,便可以投入使用。

使用 Homebrew 安装 pyenv

第一步,运行下面的命令安装 pyenv:

brew install pyenv

这个命令会自动下载安装最新版本的 pyenv,并自动下载依赖包,安装完成后,可以运行 which pyenv 命令,查看 pyenv 命令是否存在。

第二步,初始化 pyenv(pyenv init
pyenv 的工作原理 是在 PATH 环境变量的最前面添加一个垫片目录 (pyenv root)/shims,这样系统在查找 python 可执行文件时,会首先查找这个目录,进而被导引到 pyenv 管理的 python 环境,跳过后面的系统目录。
初始化 pyenv 的作用就是将垫片目录添加到 PATH 的最前面,为了每次启动 shell 都自动初始化,可以在配置文件 ~/.bash_profile 中写入如下内容(这里是针对 bash shell 而言,其它类型的 shell,配置文件的名称有所差别):

if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)";fi

或者:

if which pyenv >/dev/null; then eval "$(pyenv init -)";fi

这两句的效果是一样的,意思是判断 pyenv 命令是否存在(但不会给出此判断的结果信息),如果存在的话,执行 eval "$(pyenv init -)" 命令。
如果确定系统中pyenv 命令存在,那么可以直接添加以下内容到 ~/.bash_profile,以提高终端的打开速度:

eval "$(pyenv init -)"

最后,通过 source ~/.bash_profile 命令使设置立即生效。

从 Github 克隆 pyenv 仓库

第一步,执行以下命令:

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

这个命令会从 Github 克隆最新版本的 pyenv 仓库到本地目录 ~/.pyenv,使用这个命令的前提是安装好了 Git(Git 是一个非常好用的版本管理工具,直接使用命令 brew install git 就可以安装)。
注意这里是将 pyenv 克隆到了目录 ~/.pyenv,也可以自己选择要克隆到的目录。

第二步,克隆成功之后,还需要修改 PATH 环境变量,以使 pyenv 能够使用。在 ~/.bash_profile 文件中添加以下内容(这里是针对 bash shell 而言,其它类型的 shell,配置文件的名称有所差别):

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"

这里变量 PYENV_ROOT 的值要设置为第一步 pyenv 克隆到的目录,也可以直接在终端执行以下命令,可以获得相同的效果:

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile

设置完成后,可以运行 which pyenv 命令,查看 pyenv 命令是否存在。

注意使用 Homebrew 安装 pyenv 是不需要第二步的,Homebrew 在安装 pyenv 时已经自动设好了(安装时在 usr/local/bin 目录下建立了 pyenv 的替身,而 usr/local/bin 目录已经在 PATH 环境变量中了)。

第三步,初始化 pyenv(pyenv init
~/.bash_profile 中写入如下内容(这里是针对 bash shell 而言,其它类型的 shell,配置文件的名称有所差别):

if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)";fi

或者:

if which pyenv >/dev/null; then eval "$(pyenv init -)";fi

或者直接:

eval "$(pyenv init -)"

最后,通过 source ~/.bash_profile 命令使设置立即生效。

pyenv 的使用

目前,可用的 pyenv 命令总共只有 11 个,文档 Command Reference 里有具体说明,本文基于个人经验针对常用的一些命令在下面进行说明。

pyenv commands

列出所有可用的pyenv命令,用法是:

pyenv commands

pyenv install

安装特定版本的 python,用法是:

pyenv install [options] <version>

常用的选项 options 有:

-f/--force  :强制安装,即使该版本已经安装过了
-s/--skip-existing  :跳过已经安装过的版本
-v/--verbose:输出安装过程中的详细状态信息

另外,pyenv install --list 命令可以列出所有可以安装的 python 版本,返回的结果中,以单纯数字表示的版本是官方的版本。

就我个人经验而言,用 pyenv 安装 python 时比较容易出错,有许多地方需要注意:

首先,安装 python 前需要先安装所需的依赖包。
对 Mac os 系统而言,如果没有安装 Xcode 命令行工具,需要先安装:

xcode-select --install

另外,还需要安装以下 5 个依赖包:

brew install openssl readline sqlite3 xz zlib

可以先通过 brew list 命令查看是否已经安装过某些依赖包,只需要安装缺少的依赖包就可以了。
对于 10.14 以上的系统而言,还需要安装额外的软件开发工具包(sdk),具体请查看文档Requirements,有的已经安装过了,就不需要重复安装了(其它操作系统也可以查看 Requirements 获取帮助)。

第二,即使所需的依赖包已经全都安装好了,在安装 python 时也可能会出错,原因是安装时链接器找不到所需要的依赖包,就会认为相关的依赖包没有安装,给出错误提示,比如提示 zlib 没有安装,那么可以在安装 python 时,在安装命令前添加几个参数,如下:

CFLAGS="-I$(brew --prefix zlib)/include" \
LDFLAGS="-L$(brew --prefix zlib)/lib" \
pyenv install -v <version>

上面的安装命令中,
CPPFLAGS 是 c 和 c++ 编译器的选项,这里指定了 zlib 头文件的位置,
LDFLAGS 是 gcc 等编译器会用到的一些优化参数,这里是指定了 zlib 库文件的位置,
$(brew --prefix zlib) 这一部分的意思是在终端里执行括号里的命令,显示 zlib 的安装路径,可以事先执行括号里的命令,用返回的结果替换 $(brew --prefix zlib),效果是一样的,
每一行行尾的反斜杠可以使换行时先不执行命令,而是把这三行内容当作一条命令执行,
如果有多个依赖包都找不到,可以在引号里继续添加其它依赖包的信息,如:

CFLAGS="-I$(brew --prefix zlib)/include -I$(brew --prefix sqlite3)/include" \
LDFLAGS="-L$(brew --prefix zlib)/lib -L$(brew --prefix sqlite3)/lib" \
pyenv install -v <version>

-v 选项显示安装时的细节,
在安装命令前加上这两个参数后,链接器就可以找到相应的依赖包,可以成功安装。
具体可以参考文档 Common build problems

第三,使用 pyenv 安装 python 时,默认从 python.org 下载指定版本,往往特别慢,可以先从官网下载所需要的版本的源代码到 ~/.pyenv/cache 目录下,再执行安装命令,注意这里下载的是类似于 Python-3.7.3.tar.xz 这样的压缩文件。

pyenv uninstall

卸载某个版本的 python,用法是:

pyenv uninstall [-f|--force] <version>

-f|--force 选项的作用是强制删除某版本的 python,不需要确认,如果该版本不存在,也不会给出错误信息。

pyenv version

显示当前使用的 python 版本,用法是:

pyenv version

在版本后面会显示当前版本是如何设置的。

pyenv versions

列出所有被 pyenv 管理的 python 版本,用法是:

pyenv versions

在当前使用的版本前会用 * 标出。

pyenv local

设置当前目录下所使用的 python 版本,用法是:

pyenv local <version>

这个命令会在当前目录下的 .python-version 文件里写入版本设置信息,单纯使用 pyenv local 命令会显示当前目录所使用的 python 版本。
如果要取消设置当前目录的 python 版本,使用如下命令:

pyenv local --unset

pyenv global

设置全局使用的 python 版本,用法是:

pyenv global <version>

这个命令会在 ~/.pyenv/version 文件里写入全局的版本设置信息,单纯使用 pyenv global 命令显示当前全局使用的 python 版本(一般不建议更改全局的 python 版本,可能会引起一些系统的问题)。
如果要取消设置当前 shell 的 python 版本,使用如下命令:

pyenv shell --unset

pyenv shell

设置当前 shell 所使用的 python 版本,用法是:

pyenv shell <version>

这个命令会设置环境变量 PYENV_VERSION 的值为指定版本,也可以直接设定环境变量 PYENV_VERSION 的值,效果一样:

export PYENV_VERSION=<version>

单纯使用 pyenv shell 命令显示当前 shell 使用的 python 版本。

pyenv rehash

更新垫片目录 shims 的内容,以使 pyenv 知道它所管理的 python 版本的最新信息,用法是:

pyenv rehash

一般在安装新一个版本的 python 之后运行此命令。

pyenv 的其它操作

更新 pyenv

如果是使用 Homebrew 安装的 pyenv,那么只需要执行 brew upgrade pyenv 命令即可将 pyenv 更新至最新版本;
如果是从 Github 克隆的 pyenv 仓库,那么需要先进入到本地的 pyenv 目录 (cd $(pyenv root)),然后执行 git pull 命令,可以将 pyenv 更新至最新版本。

使 pyenv 失效

如果想暂时使 pyenv 管理 python 版本的功能失效,只需要将之前写入 ~/bash_profile 的下列内容注释掉即可:

if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)";fi

或者:

if which pyenv >/dev/null; then eval "$(pyenv init -)";fi

注释掉后,pyenv 命令仍然可以使用,但 python 程序就不会受 pyenv 版本管理的影响了(此时恢复成系统目录中的 python 版本)。

卸载 pyenv

第一步,把 ~/.bash_profile 里关于 pyenv 的内容删除掉。

第二步,如果是使用 Homebrew 安装的 pyenv,那么只需要执行 brew uninstall pyenv 命令即可将 pyenv 从计算机卸载;如果是从 Github 克隆的 pyenv 仓库,那么需要将本地的 pyenv 目录删除(rm -rf ~/.pyenv)。

pyenv-virtualenv

pyenv-virtualenv 是一个管理 python 虚拟环境的 pyenv 插件,具体可以查看 pyenv-virtualenv 文档

关于 python 虚拟环境

Python 虚拟环境是一个虚拟化,从电脑独立开辟出来的环境,它以某个版本的 python 为基础,在虚拟环境中可以安装项目所需的第三方库而不会对外界产生影响,虚拟环境的数量并没有限制,这样每个项目就可以有互相独立的运行环境,非常便于项目开发。
python 虚拟环境相当于一个独立的 python 版本,有自己独立的目录,也可以独立的安装第三方库,而不会相互干扰。

pyenv-virtualenv 的安装

同样,安装 pyenv-virtualenv 也有两种方式:使用 Homebrew 安装和从 Github 克隆。

使用 Homebrew 安装 pyenv-virtual

第一步,运行下面的命令安装 pyenv-virtualenv:

brew install pyenv-virtualenv

这个命令会自动下载安装最新版本的 pyenv-virtualenv,并自动下载依赖包,安装完成后,可以运行 which pyenv-virtualenv 命令,查看是否安装成功。

第二步,初始化
在配置文件 ~/.bash_profile 中写入如下内容(这里是针对 bash shell 而言,其它类型的 shell,配置文件的名称有所差别):

if which pyenv-virtualenv >/dev/null; then eval "$(pyenv virtualenv-init -)";fi

或者直接:

eval "$(pyenv virtualenv-init -)"

最后,通过 source ~/.bash_profile 命令使设置立即生效。

从 Github 克隆 pyenv-virtualenv 仓库

第一步,在终端执行以下命令:

git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv

这个命令会从 Github 克隆最新版本的 pyenv-virtualenv 仓库到本地目录 $(pyenv root)/plugins/pyenv-virtualenv,其中 $(pyenv root) 是指 pyenv 的安装目录。
这里要注意,如果之前安装 pyenv 时不是克隆到本地目录 ~/.pyenv,那么此处克隆时,要确保克隆到之前 pyenv 的目录下的 plugin 子目录下(没有则创建之)。
克隆完成后可以运行 which pyenv-virtualenv 命令,查看是否安装成功。

第二步,初始化
在配置文件 ~/.bash_profile 中写入如下内容(这里是针对 bash shell 而言,其它类型的 shell,配置文件的名称有所差别):

if which pyenv-virtualenv >/dev/null; then eval "$(pyenv virtualenv-init -)";fi

或者直接:

eval "$(pyenv virtualenv-init -)"

最后,通过 source ~/.bash_profile 命令使设置立即生效。

pyenv-virtualenv 的使用

创建虚拟环境

pyenv virtualenv [version] <virtualenv-name>

这个命令可以以某版本的 python 为基础创建名为 virtualenv-name 的虚拟环境,如果不指定 python 的版本,那么就会以当前的 python 版本为基础创建虚拟环境。
虚拟环境创建时,会在 $(pyenv root)/versions 目录下创建一个对应虚拟环境名的目录,这个目录只是一个链接,真身在对应的 python 版本目录下的 envs 目录下。

列出所有的虚拟环境

pyenv virtualenvs

这个命令会列出所有存在的虚拟环境,每个虚拟环境会出现两次,分别对应相应虚拟环境目录的真身和链接。

激活和关闭虚拟环境

pyenv activate <virtualenv-name>
pyenv deactivate

这两个命令分别用于激活和关闭虚拟环境。

另外,需要注意的是,通过 pyenv local <version> 命令可以为某个目录指定所使用的 python 版本,此处可以把版本名替换为某个虚拟环境名,也就是说可以为某个目录指定所使用的虚拟环境,此时在相应的 .python-version 文件中记录的就是指定的虚拟环境名。在这种情况下,当进入这个目录时,会自动激活相应的虚拟环境,退出这个目录时,会自动关闭相应的虚拟环境(在 pyenv 中,虚拟环境和正式的 python 版本具有同样的地位,通过 pyenv versions 查看 python 版本时,虚拟环境也是作为一个独立的 python 版本出现的)。

删除虚拟环境

pyenv virtualenv-delete <virtualenv-name>

这个命令用于删除某个虚拟环境,通过以下命令也可以达到同样的效果:

pyenv uninstall <virtualenv-name>

另外,也可以直接删除虚拟环境对应的目录。

pyenv-virtualenv 的其它操作

更新 pyenv-virtualenv

如果是使用 Homebrew 安装的 pyenv-virtualenv,那么只需要执行 brew upgrade pyenv-virtualenv 命令即可将 pyenv-virtualenv 更新至最新版本;
如果是从 Github 克隆的 pyenv-virtualenv 仓库,那么需要先进入到本地的 pyenv-virtualenv 目录 ,然后执行 git pull 命令,可以将 pyenv-virtualenv 更新至最新版本。

卸载 pyenv-virtualenv

第一步,把 ~/.bash_profile 里关于 pyenv-virtualenv 的内容删除掉。

第二步,如果是使用 Homebrew 安装的 pyenv-virtualenv,那么只需要执行 brew uninstall pyenv-virtualenv 命令即可将 pyenv-virtualenv 从计算机卸载;如果是从 Github 克隆的 pyenv-virtualenv 仓库,那么需要将本地的 pyenv-virtualenv 目录删除。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 140,856评论 1 295
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 60,475评论 1 254
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 92,639评论 0 208
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 40,628评论 0 171
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 48,311评论 1 250
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,533评论 1 167
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,235评论 2 266
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,017评论 0 161
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 28,738评论 6 225
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,358评论 0 211
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,115评论 2 211
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,444评论 1 222
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,138评论 0 31
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 26,965评论 2 209
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,349评论 3 200
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,574评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 25,901评论 0 163
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,314评论 2 227
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,433评论 2 228

推荐阅读更多精彩内容