5

在Linux安装或管理多个Python版本

 3 years ago
source link: https://note.qidong.name/2021/05/multiple-python/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在Linux安装或管理多个Python版本

2021-05-13 19:04:55 +08  字数:4772  标签: Linux Python

Ubuntu 20.04的Python默认版本是3.8,符合正常使用要求。 而Ubuntu 18.04上是3.6版本,更早的16.04上则是3.5版本。 而Debian的稳定版buster,如今才3.7,Deepin也同样。 在以前,Python两年发一版时,Debian这个节奏还勉强能接受;现在一年一版,就显得过于落后了。 目前(2021年5月),Python最新稳定版是3.9,3.10还处于alpha阶段。

如果因为某些原因,需要在各发行版上使用其它Python版本,就需要额外安装。 其实,deb系里,说的就是Deepin。 Ubuntu并不算落后,Debian也可以用unstable或testing的源,唯有Deepin菜得难以接受。

环境准备

sudo apt-get install -y \
    build-essential \
    curl \
    git \
    libbz2-dev \
    libffi-dev \
    liblzma-dev \
    libncurses5-dev \
    libncursesw5-dev \
    libreadline-dev \
    libsqlite3-dev \
    libssl-dev \
    llvm \
    python-openssl \
    tk-dev \
    wget \
    xz-utils \
    zlib1g-dev

以上是Ubuntu中,下载、编译Python源码所需要的环境。 后面的几种方案,都共同依赖于这些软件包。

从源码编译安装

cd /tmp
wget https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tar.xz
tar -xf Python-3.9.5.tar.xz
cd Python-3.9.5
./configure --enable-optimizations --prefix=$HOME/.python/3.9.5
make -j8
make install
cd $HOME/.python
ln -s 3.9.5 default

如果要为所有用户全局安装,可以把安装位置选择在/opt/python/,然后sudo make install。 安装完成后,把安装位置添加到PATH前面,覆盖系统版本:

# In ~/.bashrc
export PATH=$HOME/.python/default/bin:$PATH
# Or for global /etc/profile
export PATH=/opt/python/default/bin:$PATH

如果要支持多版本,以上那个default的软链接就能产生价值了。 在相同目录下安装其它版本,然后把软连接替换过去就行。

update-alternatives

有没有办法可以免配置PATH,不用手动操作软链接,也能自动管理多个Python的版本?

有,update-alternatives欢迎你。

新增候选

在源码make编译完成后,sudo make install/opt/python/3.9.5目录。 然后执行以下命令:

#    update-alternatives --install <link>                 <name>  <path>                        <priority>
sudo update-alternatives --install /usr/local/bin/python3 python3 /opt/python/3.9.5/bin/python3 80

update-alternatives的原理是,在指定的<link>位置,创建软链接<link> -> /etc/alternatives/<name>。 然后再创建软链接/etc/alternatives/<name> -> <path>。 由于在PATH中,/usr/local/bin默认排在/usr/bin前面,所以这个新的python3会被优先使用,实现对系统版本的替代。

<priority>是指,在同时存在多个版本时,默认使用哪一个。 数值越大,优先级越高。

更新候选

同样的命令,可以更新既有候选的优先级。

sudo update-alternatives --install /usr/local/bin/python3 python3 /opt/python/3.9.5/bin/python3 50

也可以增加新的候选,比如系统原有的/usr/bin/python3

sudo update-alternatives --install /usr/local/bin/python3 python3 /usr/bin/python3 100

查询候选

通过--query <name>,可以查询某个候选的情况。

$ update-alternatives --query python3
Name: python3
Link: /usr/local/bin/python3
Status: auto
Best: /usr/bin/python3
Value: /usr/bin/python3

Alternative: /opt/python/3.9.5/bin/python3
Priority: 50

Alternative: /usr/bin/python3
Priority: 100

以上就是刚才设置的两个python3的候选版本。 如果--install了更多版本,也可在此查到。

如果要查询python3以外的全部候选,可以运行update-alternatives --all,但不推荐。 这个信息很多,而且还需要处理优先级相同的一些情况。 因此,还不如去ls /etc/alternatives

调整候选版本

在自动模式下,/usr/alternatives/python3会链接到优先级最高的那个版本。 如果需要手动调整,需要使用--set <name> <path>

$ sudo update-alternatives --set python3 /opt/python/3.9.5/bin/python3
update-alternatives: using /opt/python/3.9.5/bin/python3 to provide /usr/local/bin/python3 (python3) in manual mode
$ update-alternatives --query python3
Name: python3
Link: /usr/local/bin/python3
Status: manual
Best: /usr/bin/python3
Value: /opt/python/3.9.5/bin/python3

Alternative: /opt/python/3.9.5/bin/python3
Priority: 50

Alternative: /usr/bin/python3
Priority: 100
$ /usr/local/bin/python3 --version
Python 3.9.5

--set后,再用--query查看,可以发现Status变成了manual,即手动模式。 用--set可以对python3的版本进行任意切换。 如果要改回去,可以用--auto <name>

$ sudo update-alternatives --auto python3
update-alternatives: using /usr/bin/python3 to provide /usr/local/bin/python3 (python3) in auto mode

删除

如果需要删除某个版本,可以使用--remove <name> <path>

sudo update-alternatives --remove python3 /opt/python/3.9.5/bin/python3

如果需要删除某个候选,可以使用--remove-all <name>

sudo update-alternatives --remove-all python3

pyenv

除了在系统中管理多个Python版本以外,如何发现、下载、编译,也是个问题。 pyenv是这方面最流行的解决方案。

pyenv

尽管久闻大名,但孤对这个方案还是无比抗拒,所以拖到最近才研究。 要注意的是,它只是开发环境的方案,不适合做生产环境。

安装pyenv

curl https://pyenv.run | bash

网络正常的话,以上安装是便捷无痛的。 然而,其中很重要的一步,就是去GitHub上clone它的几个代码库下来。 所以,也许需要参考一下《利用github.com.cnpmjs.org快速下载GitHub仓库》。

配置pyenv

安装完成后,还需要把以下内容,加到~/.bashrc中。

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH"
export PYENV_SHELL="bash"
source "$PYENV_ROOT/completions/pyenv.bash"

另一个选择是用eval,如果你不在意它做了什么。 而且,上面的配置去掉了对pyenv-virtualenv的支持。 所以,如果需要傻瓜式完整配置,那么可以使用下面这些。

eval "$(pyenv init -)"
eval "$(pyenv virtulenv-init -)"

pyenv的可执行文件,在$PYENV_ROOT/bin下。 而它所管理的默认Python相关可执行文件,包括pythonpydocpip等,会软链接到$PYENV_ROOT/shims下。 除了安装以外,在版本管理上,它和update-alternatives使用了类似的思路和技术。

pyenv安装新版本

列出可选安装的Python版本:

$ pyenv install --list
Available versions:
  2.1.3
  2.2.3
  2.3.7
  2.4.0
  2.4.1
  2.4.2
  2.4.3
  2.4.4
  2.4.5
  2.4.6
  2.5.0
  2.5.1
  2.5.2
  2.5.3
  2.5.4
  2.5.5
  2.5.6
  2.6.6
  2.6.7
  2.6.8
  2.6.9
  2.7.0
  2.7-dev
  2.7.1
  2.7.2
  2.7.3
  2.7.4
  2.7.5
  2.7.6
  2.7.7
  2.7.8
  2.7.9
  2.7.10
  2.7.11
  2.7.12
  2.7.13
  2.7.14
  2.7.15
  2.7.16
  2.7.17
  2.7.18
  3.0.1
  3.1.0
  3.1.1
  3.1.2
  3.1.3
  3.1.4
  3.1.5
  3.2.0
  3.2.1
  3.2.2
  3.2.3
  3.2.4
  3.2.5
  3.2.6
  3.3.0
  3.3.1
  3.3.2
  3.3.3
  3.3.4
  3.3.5
  3.3.6
  3.3.7
  3.4.0
  3.4-dev
  3.4.1
  3.4.2
  3.4.3
  3.4.4
  3.4.5
  3.4.6
  3.4.7
  3.4.8
  3.4.9
  3.4.10
  3.5.0
  3.5-dev
  3.5.1
  3.5.2
  3.5.3
  3.5.4
  3.5.5
  3.5.6
  3.5.7
  3.5.8
  3.5.9
  3.5.10
  3.6.0
  3.6-dev
  3.6.1
  3.6.2
  3.6.3
  3.6.4
  3.6.5
  3.6.6
  3.6.7
  3.6.8
  3.6.9
  3.6.10
  3.6.11
  3.6.12
  3.6.13
  3.7.0
  3.7-dev
  3.7.1
  3.7.2
  3.7.3
  3.7.4
  3.7.5
  3.7.6
  3.7.7
  3.7.8
  3.7.9
  3.7.10
  3.8.0
  3.8-dev
  3.8.1
  3.8.2
  3.8.3
  3.8.4
  3.8.5
  3.8.6
  3.8.7
  3.8.8
  3.8.9
  3.8.10
  3.9.0
  3.9-dev
  3.9.1
  3.9.2
  3.9.3
  3.9.4
  3.9.5
  3.10.0b1
  3.10-dev
  3.11-dev
  activepython-2.7.14
  activepython-3.5.4
  activepython-3.6.0
  anaconda-1.4.0
  anaconda-1.5.0
  anaconda-1.5.1
  anaconda-1.6.0
  anaconda-1.6.1
  anaconda-1.7.0
  anaconda-1.8.0
  anaconda-1.9.0
  anaconda-1.9.1
  anaconda-1.9.2
  anaconda-2.0.0
  anaconda-2.0.1
  anaconda-2.1.0
  anaconda-2.2.0
  anaconda-2.3.0
  anaconda-2.4.0
  anaconda-4.0.0
  anaconda2-2.4.0
  anaconda2-2.4.1
  anaconda2-2.5.0
  anaconda2-4.0.0
  anaconda2-4.1.0
  anaconda2-4.1.1
  anaconda2-4.2.0
  anaconda2-4.3.0
  anaconda2-4.3.1
  anaconda2-4.4.0
  anaconda2-5.0.0
  anaconda2-5.0.1
  anaconda2-5.1.0
  anaconda2-5.2.0
  anaconda2-5.3.0
  anaconda2-5.3.1
  anaconda2-2018.12
  anaconda2-2019.03
  anaconda2-2019.07
  anaconda3-2.0.0
  anaconda3-2.0.1
  anaconda3-2.1.0
  anaconda3-2.2.0
  anaconda3-2.3.0
  anaconda3-2.4.0
  anaconda3-2.4.1
  anaconda3-2.5.0
  anaconda3-4.0.0
  anaconda3-4.1.0
  anaconda3-4.1.1
  anaconda3-4.2.0
  anaconda3-4.3.0
  anaconda3-4.3.1
  anaconda3-4.4.0
  anaconda3-5.0.0
  anaconda3-5.0.1
  anaconda3-5.1.0
  anaconda3-5.2.0
  anaconda3-5.3.0
  anaconda3-5.3.1
  anaconda3-2018.12
  anaconda3-2019.03
  anaconda3-2019.07
  anaconda3-2019.10
  anaconda3-2020.02
  anaconda3-2020.07
  anaconda3-2020.11
  graalpython-20.1.0
  graalpython-20.2.0
  graalpython-20.3.0
  graalpython-21.0.0
  graalpython-21.1.0
  ironpython-dev
  ironpython-2.7.4
  ironpython-2.7.5
  ironpython-2.7.6.3
  ironpython-2.7.7
  jython-dev
  jython-2.5.0
  jython-2.5-dev
  jython-2.5.1
  jython-2.5.2
  jython-2.5.3
  jython-2.5.4-rc1
  jython-2.7.0
  jython-2.7.1
  jython-2.7.2
  micropython-dev
  micropython-1.9.3
  micropython-1.9.4
  micropython-1.10
  micropython-1.11
  micropython-1.12
  micropython-1.13
  micropython-1.14
  miniconda-latest
  miniconda-2.2.2
  miniconda-3.0.0
  miniconda-3.0.4
  miniconda-3.0.5
  miniconda-3.3.0
  miniconda-3.4.2
  miniconda-3.7.0
  miniconda-3.8.3
  miniconda-3.9.1
  miniconda-3.10.1
  miniconda-3.16.0
  miniconda-3.18.3
  miniconda2-latest
  miniconda2-3.18.3
  miniconda2-3.19.0
  miniconda2-4.0.5
  miniconda2-4.1.11
  miniconda2-4.3.14
  miniconda2-4.3.21
  miniconda2-4.3.27
  miniconda2-4.3.30
  miniconda2-4.3.31
  miniconda2-4.4.10
  miniconda2-4.5.1
  miniconda2-4.5.4
  miniconda2-4.5.11
  miniconda2-4.5.12
  miniconda2-4.6.14
  miniconda2-4.7.10
  miniconda2-4.7.12
  miniconda3-latest
  miniconda3-2.2.2
  miniconda3-3.0.0
  miniconda3-3.0.4
  miniconda3-3.0.5
  miniconda3-3.3.0
  miniconda3-3.4.2
  miniconda3-3.7.0
  miniconda3-3.7-4.8.2
  miniconda3-3.7-4.8.3
  miniconda3-3.7-4.9.2
  miniconda3-3.8.3
  miniconda3-3.8-4.8.2
  miniconda3-3.8-4.8.3
  miniconda3-3.8-4.9.2
  miniconda3-3.9.1
  miniconda3-3.9-4.9.2
  miniconda3-3.10.1
  miniconda3-3.16.0
  miniconda3-3.18.3
  miniconda3-3.19.0
  miniconda3-4.0.5
  miniconda3-4.1.11
  miniconda3-4.2.12
  miniconda3-4.3.11
  miniconda3-4.3.14
  miniconda3-4.3.21
  miniconda3-4.3.27
  miniconda3-4.3.30
  miniconda3-4.3.31
  miniconda3-4.4.10
  miniconda3-4.5.1
  miniconda3-4.5.4
  miniconda3-4.5.11
  miniconda3-4.5.12
  miniconda3-4.6.14
  miniconda3-4.7.10
  miniconda3-4.7.12
  miniforge3-4.9.2
  miniforge3-4.10
  pypy-c-jit-latest
  pypy-dev
  pypy-stm-2.3
  pypy-stm-2.5.1
  pypy-1.5-src
  pypy-1.6
  pypy-1.7
  pypy-1.8
  pypy-1.9
  pypy-2.0-src
  pypy-2.0
  pypy-2.0.1-src
  pypy-2.0.1
  pypy-2.0.2-src
  pypy-2.0.2
  pypy-2.1-src
  pypy-2.1
  pypy-2.2-src
  pypy-2.2
  pypy-2.2.1-src
  pypy-2.2.1
  pypy-2.3-src
  pypy-2.3
  pypy-2.3.1-src
  pypy-2.3.1
  pypy-2.4.0-src
  pypy-2.4.0
  pypy-2.5.0-src
  pypy-2.5.0
  pypy-2.5.1-src
  pypy-2.5.1
  pypy-2.6.0-src
  pypy-2.6.0
  pypy-2.6.1-src
  pypy-2.6.1
  pypy-4.0.0-src
  pypy-4.0.0
  pypy-4.0.1-src
  pypy-4.0.1
  pypy-5.0.0-src
  pypy-5.0.0
  pypy-5.0.1-src
  pypy-5.0.1
  pypy-5.1-src
  pypy-5.1
  pypy-5.1.1-src
  pypy-5.1.1
  pypy-5.3-src
  pypy-5.3
  pypy-5.3.1-src
  pypy-5.3.1
  pypy-5.4-src
  pypy-5.4
  pypy-5.4.1-src
  pypy-5.4.1
  pypy-5.6.0-src
  pypy-5.6.0
  pypy-5.7.0-src
  pypy-5.7.0
  pypy-5.7.1-src
  pypy-5.7.1
  pypy2-5.3-src
  pypy2-5.3
  pypy2-5.3.1-src
  pypy2-5.3.1
  pypy2-5.4-src
  pypy2-5.4
  pypy2-5.4.1-src
  pypy2-5.4.1
  pypy2-5.6.0-src
  pypy2-5.6.0
  pypy2-5.7.0-src
  pypy2-5.7.0
  pypy2-5.7.1-src
  pypy2-5.7.1
  pypy2.7-5.8.0-src
  pypy2.7-5.8.0
  pypy2.7-5.9.0-src
  pypy2.7-5.9.0
  pypy2.7-5.10.0-src
  pypy2.7-5.10.0
  pypy2.7-6.0.0-src
  pypy2.7-6.0.0
  pypy2.7-7.0.0-src
  pypy2.7-7.0.0
  pypy2.7-7.1.0-src
  pypy2.7-7.1.0
  pypy2.7-7.1.1-src
  pypy2.7-7.1.1
  pypy2.7-7.2.0-src
  pypy2.7-7.2.0
  pypy2.7-7.3.0-src
  pypy2.7-7.3.0
  pypy2.7-7.3.1-src
  pypy2.7-7.3.1
  pypy3-2.3.1-src
  pypy3-2.3.1
  pypy3-2.4.0-src
  pypy3-2.4.0
  pypy3.3-5.2-alpha1-src
  pypy3.3-5.2-alpha1
  pypy3.3-5.5-alpha-src
  pypy3.3-5.5-alpha
  pypy3.5-c-jit-latest
  pypy3.5-5.7-beta-src
  pypy3.5-5.7-beta
  pypy3.5-5.7.1-beta-src
  pypy3.5-5.7.1-beta
  pypy3.5-5.8.0-src
  pypy3.5-5.8.0
  pypy3.5-5.9.0-src
  pypy3.5-5.9.0
  pypy3.5-5.10.0-src
  pypy3.5-5.10.0
  pypy3.5-5.10.1-src
  pypy3.5-5.10.1
  pypy3.5-6.0.0-src
  pypy3.5-6.0.0
  pypy3.5-7.0.0-src
  pypy3.5-7.0.0
  pypy3.6-7.0.0-src
  pypy3.6-7.0.0
  pypy3.6-7.1.0-src
  pypy3.6-7.1.0
  pypy3.6-7.1.1-src
  pypy3.6-7.1.1
  pypy3.6-7.2.0-src
  pypy3.6-7.2.0
  pypy3.6-7.3.0-src
  pypy3.6-7.3.0
  pypy3.6-7.3.1-src
  pypy3.6-7.3.1
  pypy3.6-7.3.2-src
  pypy3.6-7.3.2
  pypy3.6-7.3.3-src
  pypy3.6-7.3.3
  pypy3.7-c-jit-latest
  pypy3.7-7.3.2-src
  pypy3.7-7.3.2
  pypy3.7-7.3.3-src
  pypy3.7-7.3.3
  pypy3.7-7.3.4
  pyston-2.2
  stackless-dev
  stackless-2.7-dev
  stackless-2.7.2
  stackless-2.7.3
  stackless-2.7.4
  stackless-2.7.5
  stackless-2.7.6
  stackless-2.7.7
  stackless-2.7.8
  stackless-2.7.9
  stackless-2.7.10
  stackless-2.7.11
  stackless-2.7.12
  stackless-2.7.14
  stackless-3.2.2
  stackless-3.2.5
  stackless-3.3.5
  stackless-3.3.7
  stackless-3.4-dev
  stackless-3.4.2
  stackless-3.4.7
  stackless-3.5.4
  stackless-3.7.5

以上排在最前面、没有什么前缀的,就是官方版本。 除了官方CPython版本以外,它还支持anaconda、pypy、jython等其它Python实现。 这也是它最大的优势。

安装某个具体的版本,只需要复制上面列出的值即可。 比如3.9.5

$ pyenv install 3.9.5
Downloading Python-3.9.5.tar.xz...
-> https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tar.xz
Installing Python-3.9.5...
Installed Python-3.9.5 to /home/yanqd0/.pyenv/versions/3.9.5

pyenv选择版本

在运行方面,pyenv设计了一个复杂的金字塔结构,包括四层:

  • shell,开一个新的shell,里面是指定版本的Python环境。
  • local,在当前目录创建一个.python-version环境。当前目录及其子目录内,Python环境都会自动使用这个指定版本。
  • global,在用户级的~/.pyenv/version中维护一个全局版本。在前两种情况以外的场景,使用系统默认版本。
  • system,如果连~/.pyenv/version文件都没有,比如在另一个用户,则使用系统版本。

pyenv pyramid

这其实把问题搞复杂了,仿佛有了这些,大家就不用使用虚拟环境似的。 pyenv shell的设计,和pipenv shell类似,因此也被后者这类替代。 pyenv local是一个自找麻烦的功能,建议不要使用。 否则,在不同目录下Python版本不同,受伤的总会是自己。 一般,一个Python项目的开发环境会使用独立的虚拟环境。

因此,只有pyenv global值得一用。 它读写一体,用法如下:

$ pyenv global
system
$ pyenv global 3.9.5
$ pyenv global
3.9.5

如果要查询当前真正可用的Python版本是什么,可用使用pyenv versionpyenv versions

$ pyenv versions
  system
  3.8.10
* 3.9.5 (set by /home/yanqd0/.pyenv/version)
  pypy3.7-7.3.4
  pyston-2.2
$ pyenv version
3.9.5 (set by /home/yanqd0/.pyenv/version)

其中,带*的就是当前版本,默认是system,也即系统原先的版本。 如果没有用pyenv local自找麻烦,那边pyenv versionpyenv global的结果应该是一致的。

pyenv的其它子命令

通过pyenv --help,可查看其它功能。 但除了几个低频的查询子命令以外,不推荐使用pyenv的其它子命令。

$ pyenv root
/home/yanqd0/.pyenv
$ pyenv which python
/home/yanqd0/.pyenv/versions/3.9.5/bin/python
$ pyenv prefix
/home/yanqd0/.pyenv/versions/3.9.5

显然,这些查询命令有点用。 但如果清楚了其中软链接的把戏,其实也没什么用。

包括shellactivatevirtualenv等子命令,都和虚拟环境有关。 这个方案,解决不了所有问题,因此还是让其它更专业的虚拟环境方案来解决吧。 这方面,可以参考本站的《Python中的虚拟环境及其工作原理》。 让pyenv专心管好多版本的Python即可。

pyenv的shims

尽管pyenv的shims,看上去和update-alternatives/etc/alternatives目录差不多,但其实更复杂。 ~/.pyenv/shims中的每一个文件,内容都是一样的,比如~/.pyenv/shims/python3

#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

program="${0##*/}"

export PYENV_ROOT="/home/yanqd0/.pyenv"
exec "/home/yanqd0/.pyenv/libexec/pyenv" exec "$program" "$@"

显然,它不是一个软链接,而是劫持了用户的命令行调用,用自己中转了一道。 也因此,它才能在运行时动态地判断是使用shell、local、global、system中的哪个版本。

pyenv-install+update-alternatives

pyenv默认是一个用户级的解决方案。 也就是说,对root和其它用户是无效的。 但是略经调整,也能成为一个系统级的方案。

如果不使用pyenv的虚拟环境功能,也不使用复杂的shell、local、global多层级版本管理, 那么可以放弃shims技术,只用pyenv install功能。

用update-alternatives来安装pyenv

在前面安装到/opt/pyenv的基础上,使用update-alternatives可以在不修改系统PATH的情况下,使用pyenv安装的多个Python版本。

curl https://pyenv.run | sudo PYENV_ROOT="/opt/pyenv" bash
sudo update-alternatives --install /usr/local/bin/pyenv pyenv /opt/pyenv/bin/pyenv 100

环境变量等配置,也要变成全局操作。 把以下内容写入/etc/profile.d/pyenv.sh中:

export PYENV_ROOT="/opt/pyenv"
export PYENV_SHELL="bash"
source "$PYENV_ROOT/completions/pyenv.bash"

此外,为了让sudo能支持它,需要让sudo中存在这些环境变量。 把以下内容写到/etc/sudoers.d/pyenv

Defaults env_keep += "PYENV_ROOT PYENV_SHELL"

这样,pyenv对其它用户也可用。 这也可以避免因root用户的Python版本不同而导致sudo出现一些诡异问题。 但是,执行安装等写操作时,需要使用sudo

pyenv install --list
sudo pyenv install 3.8.10

而且,按照本文的配置,其虚拟环境等插件功能无效。

用update-alternatives来管理Python版本

在利用sudo pyenv install安装了想要的版本后,可以用以下命令将其添加为候选。 这样,多个不同来源的Python版本就能统一管理了。

当然,update-alternatives相比pyenv的shims技术,还是有很多不足。 比如,如果要统一管理pydoc等命令,需要使用--slave,这略显麻烦。

sudo update-alternatives \
    --install /usr/local/bin/python3 python3 /usr/bin/python3 100 \
    --slave /usr/local/bin/pydoc3 pydoc3 /usr/bin/pydoc3
sudo update-alternatives \
    --install /usr/local/bin/python3 python3 /opt/pyenv/versions/3.8.10/bin/python3 200 \
    --slave /usr/local/bin/pydoc3 pydoc3 /opt/pyenv/versions/3.8.10/bin/pydoc3
sudo update-alternatives \
    --install /usr/local/bin/python3 python3 /opt/pyenv/versions/3.9.5/bin/python3 300 \
    --slave /usr/local/bin/pydoc3 pydoc3 /opt/pyenv/versions/3.9.5/bin/pydoc3

在Python多版本环境下,pip一般通过python -m pip来运行,会更准确。

总结

从源码安装、手动管理,到update-alternatives,再到pyenv,又回归pyenv-install+update-alternatives。 本文算是把Linux下,Python多版本管理的主要骚操作都讲完了。 此外,也稍微提点了一下原理。

参考


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK