Python
This is a simple guide to set up Python in macOS / Linux. The goal is to be able to manage projects that require different Python versions (say, 3.10 vs 3.6), and that have different, potentially conflicting dependencies.
Contrary to the Zen of Python, there are a myriad of ways to achieve this very reasonable goal (see this SO question for instance). This is my way, which is nevertheless based on much testing and assessment of the pros and cons of each method.
Getting Python
Get Homebrew (macOS)
We’ll use pyenv
to install Python, but in order to get pyenv
itself I suggest using a package manager.
If you’re on Linux, I trust you know which package manager you have.
In macOS I always install Homebrew.
- First you’ll need Xcode. If you don’t know what Xcode is that’s great, because then you can get away with installing a minimal version. Run
xcode-select --install
- Installing Homebrew boils down to running
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- I suggest that right after installing Homebrew, you make sure all package definitions (a.k.a. formulae) are up-to-date, which can be done with
brew update
Install pyenv
I like using pyenv
to manage multiple Python versions, as it sticks to the Unix philosophy of doing one thing well.
- Before installing
pyenv
itself, install its appropriate Python build dependencies. In macOS, runbrew install openssl readline sqlite3 xz zlib tcl-tk
- Then, install
pyenv
withbrew install pyenv
Add pyenv
to path
The pyenv
program we just installed needs to be added to the system’s path so that it runs the appropriate version of Python whenever we type python
(more details here).
Find out which shell you’re using with
echo $0
In macOS you should get either
bash
orzsh
. Modern macOS versions should havezsh
(see screenshot below).Finally, we’ll set up our shell environment for
pyenv
. Assuming your shell iszsh
, then runecho 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc echo 'eval "$(pyenv init -)"' >> ~/.zshrc
Note: if your shell is
bash
, then replace~/.zshrc
with~/.bashrc
in the lines above.
Install Python with pyenv
pyenv
makes it easy to install any Python version that we want (for example, 3.6.4 or 3.12.0).
Moreover, it contains different Python distributions (for example, Anaconda 3 2022.05).
The full list of available installs can be obtained with
pyenv install --list
You’ll get a long list of options.
If you know which version you require (say, for a pre-existing project that contains a requirements.txt
file), you can install a specific version with pyenv install <version>
. For example,
pyenv install 3.10.9 # just an example
If you are unsure about which version to install, I’d just go with the most recent one. The latest available version can be printed out and installed using the two following commands, respectively:
# print latest version:
pyenv install --list | sed 's/^ //' | grep '^\d' | grep --invert-match 'dev\|a\|b' | tail -1
# install latest version:
pyenv install $(pyenv install --list | sed 's/^ //' | grep '^\d' | grep --invert-match 'dev\|a\|b' | tail -1)
If you know which version of Python you want (say, 3.9), then you can omit the revision and pyenv
will resolve the request to the latest available revision:
pyenv install 3.9 # installs 3.9.16
Keep in mind that you can always add or remove versions, so this decision is not final.
To uninstall a version, simply use pyenv uninstall <version>
. See here for more info.
Set up a global Python version
Now that Python 3 is installed via pyenv
, we need to set it as a global (i.e. system default) version.
You can check out the available Python versions in your machine with
pyenv versions
The output I get after running this command in my local machine is above. Notice that there is an asterisk next to 3.8.6
: this indicates it’s the active version, which in this case, it’s the one I’ve set up as my global Python version. This can also be obtained by running pyenv version
(singular).
We can change the global default version by running pyenv global <version>
, where <version>
is any of the ones listed when running pyenv versions
. For example, I can switch my global default version to 3.6.13 by running
pyenv global 3.6.13 # just an example
I can check that this worked by running pyenv version
again, or simply by initializing the Python REPL with python
. See output below.
If you only need one Python version for all your projects, and you’d prefer it wasn’t the system default (as you should), then having a single global version should work just fine. Up next, we’ll walk through how to set up projects that need different Python versions and environments.
Project-specific Python environments
In many instances we want to be able to create project-specific Python environments for our projects. That is, we want to
- use a specific Python version (say, 3.9.16), and
- have project-specific dependencies (libraries).
In order to fix ideas, suppose we want to create a new project ("foo
") located in ~/foo
.
Local Python version
Defining a local Python version enables easy switching to the Python required by a particular project.
We can define a local Python version using pyenv local <version>
inside the project’s root directory:
cd ~/foo
pyenv local 3.9.16
This will create a .python-version
file inside ~/foo
, and every Python call issued inside foo
will use the version defined here, taking precedence over the global version.
IDEs like VSCode will automatically detect this file and set the Python version accordingly.
Virtual environments
Virtual environments permit project-specific dependencies. That is, a virtual environment allow us to install libraries which are tied to a specific project. This is great because different projects might have different, potentially conflicting dependencies.
We can create a virtual environment for our foo
project by running
cd ~/foo
python -m venv .venv
This will create a virtual environment inside ~/foo
, which is really just a directory named .venv
(or anything else, really) where the project libraries are installed.
Because of this, we can delete a virtual environment by simply removing this directory (rm -rf .venv
; be careful with rm -rf
!).
Finally, we need to activate the virtual environment prior to using it. In Unix, this is done with
cd ~/foo
source .venv/bin/activate
References
- https://opensource.com/article/19/6/python-virtual-environments-mac
- https://www.freecodecamp.org/news/python-version-on-mac-update/
- https://stackoverflow.com/questions/29687140/install-latest-python-version-with-pyenv
- https://stackoverflow.com/questions/41573587/what-is-the-difference-between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe
- https://realpython.com/intro-to-pyenv/