Skip to content

Pyenv 对 Python 进行版本管理

约 3127 字大约 10 分钟

Python

2025-01-20

pyenv是管理python版本的工具。安装pyenv后,可以管理各种python版本,并且各个版本的环境完全独立,互不干扰。

pyenv是一个forkedruby社区的简单、低调、遵循UNIX哲学的Python环境管理工具, 它可以轻松切换全局解释器版本, 同时结合vitualenv插件可以方便的管理对应的包源。

安装

查看pyenv版本

$ pyenv version
zsh: command not found: pyenv

没发现pyenv则表示没安装。

GitHub拉源码安装

pyenv已经在github上开源,我们直接从githubclone项目到本地。

$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
Cloning into '/Users/matias/.pyenv'...
remote: Enumerating objects: 21745, done.
remote: Counting objects: 100% (503/503), done.
remote: Compressing objects: 100% (151/151), done.
remote: Total 21745 (delta 369), reused 439 (delta 334), pack-reused 21242
Receiving objects: 100% (21745/21745), 4.37 MiB | 57.00 KiB/s, done.
Resolving deltas: 100% (14709/14709), done.

使用Homebrew安装

MacOS可以直接用homebrew安装

$ brew install pyenv    
Running `brew update --auto-update`...

...

For more information about Homebrew and Python, see: https://docs.brew.sh/Homebrew-and-Python

安装完成之后查看

$ pyenv version
system (set by /Users/matias/.pyenv/version)

注意 如果提示homebrew且等待了很久,则可以Control + C结束homebrew的更新。

配置环境

添加shell配置(如:.zshrc.bashrc

$ vim ./zshrc
$ sudo vim ./zshrc

添加如下配置

export PYENV_ROOR="$HOME/.pyenv"
export PATH=$PYENV_ROOT/shims:$PATH
# eval "$(pyenv init --path)"或eval "$(pyenv init -)"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

刷新配置

$ source ~/.zshrc
$ source ~/.zprofile

如果您还希望在非交互式登录 shell 中获取 Pyenv,还可以将命令添加到.profile.zprofile.zlogin

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zprofile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zprofile
echo 'eval "$(pyenv init --path)"' >> ~/.zprofile

使用

注意 如果要通过共享库的方式安装Python,可使用如下命令:

$ env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.5.2

查看版本

$ pyenv version
system (set by /Users/matias/.pyenv/version)

查看可安装的Python版本

$ pyenv install -l
Available versions:
  ...
  3.10.0
  3.10-dev
  3.10.1
  3.10.2
  3.10.3
  3.10.4
  3.10.5
  3.10.6
  3.10.7
  3.10.8
  3.10.9
  3.10.10
  3.11.0
  3.11-dev
  3.11.1
  3.11.2
  3.12.0a5
  3.12-dev

安装新的Python版本,遇到编译失败,可以参考官方提供的解决方案 Common-build-problems

$ pyenv install 3.10.5

查看信息

$ pyenv install -v 3.10.5

查看所有版本

$ pyenv versions

全局使用某个版本

$ pyenv global 3.6.12

查看是否切换成功

$ python --version

实际上当你切换版本后, 相应的pip和包仓库都是会自动切换过去的

更多命令如下:

pyenv commands:查看所有pyenv命令 pyenv exec:使用特定Python版本执行某条命令 pyenv global:设置或查看全局Python版本 pyenv hooks:列出给出的pyenv命令的钩子脚本 pyenv init:配置shell环境 pyenv install:安装某个版本的Python pyenv local:为某个应用设置特定的Python版本 pyenv prefix:显示对应Python版本的路径前缀 pyenv rehash:再哈希pyenv shims(不清楚有什么用,欢迎评论补充) pyenv root:显示pyenv根目录 pyenv shell:为某个shell设置特定的Python版本(与pyenv local类似) pyenv shims:列出当前存在的shims(pyenv的工作原理就是在一个叫shims的目录下创建Python解释器的“假版本”,寻找Python应用时先从该目录查找) pyenv uninstall:卸载某个版本Python pyenv --version:显示pyenv版本 pyenv version:显示当前Python版本,等价于pyenv version-name+pyenv version-file pyenv version-file/version-name/version-origin:当前Python版本对应的文件/名字/位置 pyenv whence:列出已安装的一个范围内的Python版本,比如列出本地安装的Python2到Python3的版本,可以使用pyenv whence 2to3 pyenv which:列出可执行文件的绝对路径,比如pyenv which python可以列出python命令的绝对路径

globalshelllocal之间的区别:

  • global 全局设置:如果使用此命令,可以看到所有受到pyenv控制的窗口都受到了影响, 所以尽可能不要用root用户来安装pyenv,否则会影响到之前的系统
  • shell 会话设置(只影响当前的会话)
  • local 本地设置(只影响所在文件夹)

pyenv-virtualenv创建虚拟环境

安装pyenv-virtualenv

$ arch -arm64 brew install pyenv-virtualenv
...
To enable auto-activation add to your profile:
  if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi

注意 安装完成需要配置eval "$(pyenv virtualenv-init -)"到环境变量中去。

首先下载pyenv-virtualenv插件

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

克隆完成后添加如下到shell配置文件(mac的话是.zshrc)

$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile

实际上mac用户直接brew安装就可以了...

$ brew install pyenv-virtualenv
$ eval "$(pyenv init -)"
$ eval "$(pyenv virtualenv-init -)"

创建虚拟环境

创建一个Python 3.10.5版本的虚拟环境, 命名为venv

$ pyenv virtualenv 3.10.5 venv

查看目前的所有的虚拟环境

$ pyenv virtualenvs

激活名为venv的虚拟环境

$ pyenv activate venv

关闭虚拟环境

$ pyenv deactivate venv

当切换Python解释器的时候对应的pip和包库也会一并切换过去, 而且可以为指定版本的解释器创建项目所需的虚拟环境, 切换的时候也异常简单, 个人常用的做法是为每个项目创建不同的虚拟环境, 当进入该环境的时候就可以随便浪而不用担心影响到其它项目, 搭配编辑器如:PycharmVSCode使用效果更佳。

对比

pyenvpipenvvirtualenv的关系

pipenvrequests 作者 Kenneth Reitz写的一个python虚拟环境管理工具, 结合了pipvirtualenv的功能, 侧重点还是在包环境管理上, 使用思路是先创建一个指定python版本的环境, 然后在此环境上安装相应的包。

virtualenv是一个比较传统成熟的虚拟环境管理工具了, 用的人也比较多, 思路也是创建虚拟环境, 然后安装相应的包, 要进入环境就source一下activate脚本激活一下。

pyenv相对于其他两个工具, pyenv更侧重在 python 解释器版本管理上, 比包管理更大一个层级, 使用pyenv我可以方便的下载指定版本的python解释器, pypy, anaconda等, 可以随时自由的在shell环境中本地、全局切换python解释器。pyenv切换解释器版本的时候, pippython以及对应的包环境都是一起切换的, 所以如果你要同时运行python2.xpython3.x多个解释器验证一些代码时就很方便。pyenv也可以创建好指定的虚拟环境, 但不需要指定具体目录, 自由度更高, 使用也简单。

错误

BUILD FAILED (OS X 11.5.1 using python-build 2.3.2-7-g16f7ea03)

安装新的Python版本pyenv install 3.10.5pyenv install -v 3.10.5报错#1245

ld: warning: ld: warning: directory not found for option '-L/Users/matias/.pyenv/versions/3.10.5/lib'directory not found for option '-L/Users/matias/.pyenv/versions/3.10.5/lib'

ld: warning: directory not found for option '-L/Users/matias/.pyenv/versions/3.10.5/lib'
ld: warning: directory not found for option '-L/Users/matias/.pyenv/versions/3.10.5/lib'
Undefined symbols for architecture x86_64:
  "_libintl_bindtextdomain", referenced from:
Undefined symbols for architecture x86_64:
  "_libintl_bindtextdomain", referenced from:
      __locale_bindtextdomain in libpython3.10.a(_localemodule.o)
      __locale_bindtextdomain in libpython3.10.a(_localemodule.o)
  "_libintl_dcgettext", referenced from:
  "_libintl_dcgettext", referenced from:
      __locale_dcgettext in libpython3.10.a(_localemodule.o)
  "_libintl_dgettext", referenced from:
      __locale_dcgettext in libpython3.10.a(_localemodule.o)
      __locale_dgettext in libpython3.10.a(_localemodule.o)
  "_libintl_dgettext", referenced from:
  "_libintl_gettext", referenced from:
      __locale_gettext in libpython3.10.a(_localemodule.o)
      __locale_dgettext in libpython3.10.a(_localemodule.o)
  "_libintl_setlocale", referenced from:
  "_libintl_gettext", referenced from:
      __locale_setlocale in libpython3.10.a(_localemodule.o)
      __locale_localeconv in libpython3.10.a(_localemodule.o)
      __locale_gettext in libpython3.10.a(_localemodule.o)
  "_libintl_textdomain", referenced from:
  "_libintl_setlocale", referenced from:
      __locale_textdomain in libpython3.10.a(_localemodule.o)
      __locale_setlocale in libpython3.10.a(_localemodule.o)
      __locale_localeconv in libpython3.10.a(_localemodule.o)
  "_libintl_textdomain", referenced from:
      __locale_textdomain in libpython3.10.a(_localemodule.o)
ld: symbol(s) not found for architecture x86_64
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Programs/_testembed] Error 1
make: *** Waiting for unfinished jobs....
make: *** [python.exe] Error 1

BUILD FAILED (OS X 11.5.1 using python-build 2.3.2-7-g16f7ea03)

Inspect or clean up the working tree at /var/folders/bz/qdc41tl10s36tg71w9qdq5jh0000gn/T/python-build.20220727103447.34041
Results logged to /var/folders/bz/qdc41tl10s36tg71w9qdq5jh0000gn/T/python-build.20220727103447.34041.log

Last 10 log lines:
      __locale_localeconv in libpython3.10.a(_localemodule.o)
  "_libintl_textdomain", referenced from:
      __locale_textdomain in libpython3.10.a(_localemodule.o)
ld: symbol(s) not found for architecture x86_64
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Programs/_testembed] Error 1
make: *** Waiting for unfinished jobs....
make: *** [python.exe] Error 1

确保安装了 Python 的二进制依赖项和构建工具。遇到编译失败,可以参考官方提供的解决方案 Common-build-problems

只需为命令添加前缀:AR=/usr/bin/env pyenv install ....AR为调用pyenv. 或者(暂时)brew uninstall binutils,如果那是ar从哪里来的(你可以检查which ar——如果它说/usr/local/bin/ar你可能已经安装了 binutils)。

$ which ar
/usr/bin/ar
$ env PYTHON_CONFIGURE_OPTS="--enable-framework --enable-universalsdk --with-universal-archs=universal2" pyenv install 3.10.5   
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Installing Python-3.10.5...
python-build: use tcl-tk from homebrew
python-build: use readline from homebrew
python-build: use zlib from xcode sdk

BUILD FAILED (OS X 12.5 using python-build 2.3.2-7-g16f7ea03)

Inspect or clean up the working tree at /var/folders/bz/qdc41tl10s36tg71w9qdq5jh0000gn/T/python-build.20220729155015.61546
Results logged to /var/folders/bz/qdc41tl10s36tg71w9qdq5jh0000gn/T/python-build.20220729155015.61546.log

Last 10 log lines:
  "_libintl_gettext", referenced from:
      __locale_gettext in libpython3.10.a(_localemodule.o)
  "_libintl_setlocale", referenced from:
      __locale_setlocale in libpython3.10.a(_localemodule.o)
      __locale_localeconv in libpython3.10.a(_localemodule.o)
  "_libintl_textdomain", referenced from:
      __locale_textdomain in libpython3.10.a(_localemodule.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Python.framework/Versions/3.10/Python] Error 1

重要 安装成功先安装了arch -arm64 brew install pyenv-virtualenv然后配置了.zshrc.zprofile

.zshrc如下:

$ cat ~/.zshrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

.zprofile如下:

$ cat ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
eval "$(/opt/homebrew/bin/brew shellenv)"

# Created by `pipx` on 2021-09-17 05:33:24
export PATH="$PATH:/Users/matias/.local/bin"
eval "$(/opt/homebrew/bin/brew shellenv)"
`pyenv`主要看下面几个
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

安装python 3.10.5

$ arch -arm64 pyenv install 3.10.5
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Installing Python-3.10.5...
python-build: use tcl-tk from homebrew
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.10.5 to /Users/matias/.pyenv/versions/3.10.5

pyenv安装python太慢慢

使用 pyenv 安装 python 时,默认从 python.org 下载指定版本,往往特别慢,经常下载失败,这时可以先从官网下载所需要的版本的源代码到 ~/.pyenv/cache 目录下,再执行安装命令(亲测很好用)。

注意 这里要下载的是类似于 Python-3.7.3.tar.xz 这样的压缩文件,要到官网 sourcecode 页面才可以下载。

如果是下载 python 源码这一步慢,可以先创建缓存目录 mkdir $PYENV_ROOT/cache 然后用别的方法下载 Python 源码放到该目录下。 这个路径是由 PYTHON_BUILD_CACHE_PATH 控制的,默认值是 "$PYENV_ROOT/cache",但是文件夹并不是默认创建的。 相关代码可以自己查看pyenv-install

使用国内源

3.7.5是版本号,-P是下载到指定目录,如果没用cache目录必须先创建此目录

$ wget http://mirrors.sohu.com/python/3.7.5/Python-3.7.5.tar.xz -P ~/.pyenv/cache/

如果有想下载其他,那么把版本号改掉即可,格式如下 $v 代表版本

$ wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/
$ wget https://npm.taobao.org/mirrors/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/

下载完成以后运行命令即可

注意 wget的方式未成功下载,好像是因为mirrors.sohu.com下面没有python的目录了

查看python的版本镜像

https://pypi.tuna.tsinghua.edu.cn/simple/   # 清华
http://pypi.doubanio.com/simple/  # 豆瓣
http://mirrors.aliyun.com/pypi/simple/  # 阿里云
http://pypi.hustunique.com/  # 华中理工大学
http://pypi.sdutlinux.org/ # 山东理工大学
https://pypi.mirrors.ustc.edu.cn/simple/ # 中国科学技术大学
http://mirrors.163.com/pypi/simple/ # 网易

清华大学开源镜像站 https://mirrors.tuna.tsinghua.edu.cn/
网易开源镜像站 http://mirrors.163.com/
阿里巴巴开源镜像站 https://opsx.alibaba.com/mirror/
网易开源镜像站http://mirrors.163.com/
搜狐镜像站(PHP,python)http://mirrors.sohu.com/
淘宝镜像 https://npm.taobao.org/mirrors/
腾讯软件源 mirrors.cloud.tencent.com/
华为开源镜像站:mirrors.huaweicloud.com/
9.中国科技大学:mirrors.ustc.edu.cn/
10.北京交通大学:mirror.bjtu.edu.cn/cn/
11.上海交通大学:ftp.sjtu.edu.cn/
12.北京理工大学:mirror.bit.edu.cn/web/
13.浙江大学:http://mirrors.zju.edu.cn
14.北京理工大学:http://mirror.bit.edu.cn
15.华中科技大学:mirrors.hust.edu.cn/
16.豆瓣http://pypi.douban.com/simple/
17.华中理工大学http://pypi.hustunique.com/simple/
18.山东理工大学 http://pypi.sdutlinux.org/simple/

上面选择一个源下载,最好先确认下路径下面有没有对应的版本文件

$ wget https://npm.taobao.org/mirrors/python/3.8.10/Python-3.8.10.tar.xz -P ~/.pyenv/cache/ 
--2023-03-07 17:18:48--  https://npm.taobao.org/mirrors/python/3.8.10/Python-3.8.10.tar.xz
Resolving npm.taobao.org (npm.taobao.org)... 114.55.80.225
Connecting to npm.taobao.org (npm.taobao.org)|114.55.80.225|:443... connected.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: https://cdn.npmmirror.com/binaries/python/3.8.10/Python-3.8.10.tar.xz [following]
--2023-03-07 17:18:48--  https://cdn.npmmirror.com/binaries/python/3.8.10/Python-3.8.10.tar.xz
Resolving cdn.npmmirror.com (cdn.npmmirror.com)... 182.140.196.215, 182.140.196.221, 182.140.196.216, ...
Connecting to cdn.npmmirror.com (cdn.npmmirror.com)|182.140.196.215|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18433456 (18M) [application/x-xz]
Saving to: ‘/Users/matias/.pyenv/cache/Python-3.8.10.tar.xz’

Python-3.8.10.tar.xz           100%[====================================================>]  17.58M  12.3MB/s    in 1.4s    

2023-03-07 17:18:50 (12.3 MB/s) - ‘/Users/matias/.pyenv/cache/Python-3.8.10.tar.xz’ saved [18433456/18433456]

参考

pip,pipenv,pyenv

Github-pyenv-installer

python版本下载地址

pyenv的github地址

pyenv-vitualenv插件地址

pyenv安装

pyenv比 pythonbrew 和 pythonz 好在哪里?

pyenv 官方安装

pyenv安装python慢