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_profileso 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-versionfile in your project. Good for locally running project files and serves as documentation.
$ pyenv virtualenv 3.6.0 venv3.6.0
venv3.6.0with 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.5then run
$ pip freeze > requirements.txtto 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.