With Yosemite around the corner it’s time to review, and maybe polish up, the toolchain setup.
OS X updates always blow away whatever hard work you’ve done crafting your environment to be Just So. As such it’s worth having it documented, and more or less scripted.
GitHub take this to the limit with their Boxen project — this uses puppet to make setting a new Mac entirely repeatable. I recommend checking this out. I use it myself to maintain a few core dependencies but — whilst I’m a big fan of puppet on the server and vagrant boxes — I still tend to favour shell scripts for my own local environment. (This is a perfectly legitimate alternative for configuration management.)
The old way
For at least a couple of major versions, setting up Python on OS X has been a simple three-liner:
sudo easy_install pip sudo pip install virtualenv sudo pip install virtualenvwrapper
The system Python has been recent enough.
pip is the Python’s package manager of choice. It learnt the lessons of
easy_install — but hasn’t been bundled by default.
virtualenv allows creating isolated per-project environments.
virtualenvwrapper adds various command-line extras to help manage
virtualenv based project workflows.
With these three in place you’d have more or less everything you need for a happy life. You might globally
pip install Fabric or IPython (and
easy_install readline — Grrrr) but everything else could be done in reproducible per-project environments, the details of which were kept in source control. It was pretty good.
And then something happened.
2014 became the year when Python 3 became not only compulsory to support but actually the place to be. Let me be clear here, Python 3 became both of these things in 2014 — before that you were free to ignore with impunity — it was neither.
But now we have a much more serious problem. The battle for Python 3 adoption is far from over. Take an article just from May 2014. It’s a great piece but it’s not “we’re mopping up on Python 2”. We now need to support, develop and test against Python 2 and Python 3 simultaneously.
So the new way
For this we’ll use the relatively new, and quite wonderful,
pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.
On top of that we’re going to use
pyenv-virtualenv which adds
virtualenv-like abilities to create isolated environments (leveraging
pyvenv for Python v3.3+) and some of the project management features of
The “some” here is important. There are a couple of conveniences from
virtualenvwrapper that we’ll be giving up.
setvirtualenvproject and others. There is a
pyenv-virtualenvwrapper plugin but it’s not been updated in a while and there’s a discussion on an issue that suggests a
pyenv-virtualenv is going to serve us better. We can add the missing conveniences ourselves later.
Install is again dead simple. This is the summary; read the READMEs:
brew update brew install pyenv brew install pyenv-virtualenv
bbedit ~/.profile to add the initialisation scripts:
eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
And that’s it!
Run through a few commands to see the joy.
pyenv versions pyenv install 3.4.2 pyenv versions pyenv shell 3.4.2 python -V cd .pyenv/ ls -1 ls -1 versions/ pyenv virtualenv 3.4.2 myvenv pyenv virtualenvs pyenv versions pyenv shell myvenv pip freeze pip install django which django-admin pip freeze
Hopefully you'll see how cool it is.