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.)
Anyhow, Python…
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
.
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 virtualenvwrapper
.
The “some” here is important. There are a couple of conveniences from virtualenvwrapper
that we’ll be giving up. cdsitepackages
, 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
Then 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.