This article is participating in Python Theme Month. See the link to the event for more details

introduce

Learn how to use PyEnv to install multiple Python versions locally without affecting work or life

Pyenv lets you easily switch between multiple Python versions. It’s simple, unobtainable, and in the TRADITION of UNIX’s single responsibility, it does one thing very well.

Install pyenv

  1. On MAC, brew is used
$ brew install pyenv
Copy the code
  1. Configure pyEnv initialization in the shell
$ echo 'eval "$(pyenv init --path)"' >> ~/.zprofile
Copy the code

For details about installation methods, see the installation documentation on the official website

Pyenv common commands

View all available Python versions

$ pyenv install -listAvailable Versions: 2.1.3 2.2.3 2.3.7 2.4.0 2.4.1 2.4.2... 3.9.1 3.9.2 3.9.3 3.9.4 3.9.5 3.10.0b2 3.10-dev 3.11-devCopy the code

Check the installed Python version

$ pyenv versionsSystem * 3.7.10 (set by/Users/zioyi /. Pyenv/version)Copy the code

Installs the specified Python version

$Pyenv install 3.10.0 b2Downloading 3.10.0 b2...-> https://downloads.python.org/3.10.0b2.tar.bz2Installing 3.10.0 b2... Installed 3.10.0 b2 to/Users/zioyi /. Pyenv/versions / 3.10.0 b2Copy the code

The global environment specifies the Python version

$Pyenv global 3.10.0 b2
$ pythonPython 3.10.0b2 (default, Jul 29 2021, 09:57:10) [Clang 12.0.5 (clang-1205.0.22.9)] on Darwin Type "help", "copyright", Python 3.10.0 B2 (default, Jul 29 2021, 09:57:10) [Clang 12.0.5 (clang-1205.0.22.9)] "credits" or "license" for more information.>>> 
Copy the code

Specify the Python version under the current shell

$ pyenv local 3.7.10
$ python
Python 3.7.10 (default, Jul 29 2021, 09:57:10) [Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Copy the code

Note: Local has a higher priority than global

Uninstall the installed Python version

$Pyenv uninstall pypy3.7-7.3.5Pyenv: remove/Users/zioyi /. Pyenv/versions/pypy3.7-7.3.5? [y | N] y pyenv: pypy3.7-7.3.5 uninstalledCopy the code

See the official command manual for more information

The principle of pyenv

In fact, the secret of PyEnv lies in the second step of installing PyEnv: initializing PyEnv

eval "$(pyenv init -)"
Copy the code

Since this line of command is written in the.zprofile file, it is executed every time you log in to the shell, and its effect is to add pyenv-related paths to the PATH

$ echo $PATH
***:/Users/zioyi/.pyenv/shims:/Users/zioyi/.pyenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:***
Copy the code

When Linux runs a command, it traverses each PATH of the PATH environment variable in order to find the command to be executed. The traversal stops when the first match is found in a directory, so in the PATH environment variable, the earlier PATH has a higher priority than the later PATH.

System default Python is commonly under the/usr/bin directory, and the path/Users/zioyi pyenv /. Pyenv/shims, before it all when we are in the shell to execute the Python command, will now pyenv catalog to find

$ which python
/Users/zioyi/.pyenv/shims/python
Copy the code

We call shim a shim, which acts as a layer of proxy between shell and Python. Pyenv creates shim for various Python version-related commands in the ~/.pyenv/shims directory

$ ls ~/.pyenv/shims2to3 Flask jupyter- Bundlerextension jupyter-troubleshoot pycodeStyle Pytest - BDD python3.7-gdb.py rst2odt_prepstyles.py 2to3-3.10 Idle Jupyter-console Jupyter-Trust Pydoc Pytest -benchmark python3.7m rst2pseudoxml.py 2to3-3.7idle3 Jupyter-kernel libpypy3-c.dylib pydoc3 python python3.7m-config rst2s5.py __pycache__ idle3.10 jupyter-kernelspec Mako-render pydoc3.10 python-config pyvenv rst2xetex. Py coverage idle3.7 jupyter-migrate pep8 pydoc3.7 python3 Pyvenv-3.7 rst2xml.py coverage-3.7 iptest jupyter-nbconvert PIP pyflakes python3-config rst2html.py rstpep2html.py Coverage3 iptest3 jupyter- nbexvector pip3 pygmentize python3.10 rst2html4.py send2Trash cpuinfo ipython Jupyter-qtconsole pip3.7pypy3 jupyter-qtconsole pip3.7pypy3 jupyter-qtconsole pip3.7pypy3 Python3.10 -gdb.py rst2latex. Py easy_install-3.7 jsonschema jupyter-run py. Test pypy3.7 python3.7 rst2man.py Flake8 Jupyter jupyter- serverExtension py.test-benchmark pytest python3.7-config rst2odt.pyCopy the code

So when we execute python-related commands, we’re actually executing these shim. The contents of these spacers are the same:

$ cat ~/.pyenv/shims/python
#! /usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

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

export PYENV_ROOT="/Users/zioyi/.pyenv"
exec "/usr/local/opt/pyenv/bin/pyenv" exec "$program" "$@"
Copy the code

When we run program “param1” “param2″… Pyenv exec “program” “param1” “param2″… . For example, if python -v is executed, pyenv exec python -v is actually executed.

In the pyenv exec command, the pyenv version name is first called to determine the Python version or virtual environment version. The search rules are:

Within the pyenv exec command, pyenv which is called again to determine the path to the executable program. If the previous Pyenv version name determines the Python or virtual environment version, Use either /versions/< version number >/bin/< program name > or < Pyenv installation path >/versions/< version number >/env/< virtual environment name >/bin/< program name >. Otherwise, go through the installation paths for all versions. Take the first matched executable in order.

After determining the executable file path corresponding to the version number, run the following command:

exec -a program "$path" "param1" "param2" 
#Note: Execution"path" "param1" "param2", and use program as the program name, which is in the shell$0, sys.argv0 in Python
Copy the code

Execute python -v, for example, to determine the pyenv version for 3.10.0 b2, corresponding to the executable file for ~ /. Pyenv/versions / 3.10.0 b2 / bin/python, execute commands as follows:

The exec - a python ~ /. Pyenv/versions / 3.10.0 b2 / bin/python -vCopy the code

That’s the basic principle of pyenv execution

conclusion

Pyenv is a great way to manage multiple versions of Python. When different projects require different Versions of Python, pyEnv can be easily managed; Pyenv can also be used when we want to try new Python3.10 and are worried about polluting our development environment.