What’s the simplest way to locally run different versions of Python and PyPi packages on macOS?
After getting back into Python recently I set out to discover this. When working on multiple projects, globally installing packages is a fast track to dependency hell.
There seem to be a few competing approaches to handling this but after some research, I found a simple approach using pyenv
and the pyenv-virtualenv
plugin that should have you up and running in no time.
First i’d recommend installing the package manager homebrew if you don’t already have it, then you can follow the guide below:
$ brew install pyenv zlib
$ brew install pyenv-virtualenv
eval "$(pyenv init -)"
and eval "$(pyenv virtualenv-init -)"
to your .bash_profile
so both of these packages are always available.$ xcode-select --install
$ pyenv install 3.6.0 && pyenv rehash
$ pyenv install --list
. You’ll need to run the rehash command any time you install a new Python version.$ pyenv local 3.6.0
.python-version
file in your project. Good for locally running project files and serves as documentation.$ pyenv virtualenv 3.6.0 venv3.6.0
venv3.6.0
with the language specified as 3.6.0 and you will use this environment to install project specific dependencies.$ pyenv activate venv3.6.0
Congratulations, you now have a way to isolate dependencies for your projects. Now to install specific dependencies and enable other developers to clone and run your project, you need to create a requirements.txt
file in the root of your project which lists your dependencies and their versions.
Then you can install packages in two ways:
$ pip install -r requirements.txt
$ pip install package_name==0.1.5
then run $ pip freeze > requirements.txt
to add them to your requirements.txt.New developers can simply clone your project and (assuming they have pyenv and pyenv-virtualenv setup) can simply create their own virtual environment as above and run $ pip install -r requirements.txt
.
Note that I did look into other solutions using Miniconda, Distutils/setup.py, Docker but the pyenv and virtualenv combination seems to be nice way to get started and avoid global dependency headaches.