Installing Python and Virtualenv on Mac OS X 10.8 Mountain Lion can be done any number of ways. While there’s no best or perfect configuration, this tutorial will guide you through the process of configuring a stock Mountain Lion installation into a rockin’ Python development system.
First steps
This guide assumes that you have already installed Xcode and Homebrew. For details, please follow the steps in the Mountain Lion Configuration Guide.
Python
We are going to install the latest 2.7.x version of Python via Homebrew. Why bother, you ask, when Apple includes Python along with Mountain Lion? Here are some reasons:
- Homebrew always has the most recent version (currently 2.7.5). The version bundled with OS X is well out-of-date at 2.7.2.
- Apple has made significant changes to its bundled Python, potentially resulting in hidden bugs.
- Homebrew’s Python includes the latest Python package management tools: pip and Setuptools
Along the same lines, Mountain Lion’s version of OpenSSL (0.9.8r) is from February of 2011, so we’re going to tell Homebrew to download the latest OpenSSL and compile Python with it.
Use the following command to install Python via Homebrew:
brew install python --with-brewed-openssl
You’ve already modified your PATH
as mentioned in the Mountain Lion Configuration Guide, right? If not, please do so now.
Optionally, we can also install Python 3.x alongside Python 2.x:
brew install python3 --with-brewed-openssl
… which makes it easy to test your code on both Python 2.x and Python 3.x.
Pip
Let’s say you want to install a Python package, such as the fantastic virtualenv environment isolation tool. While nearly every Python-related article for Mac OS X tells the reader to install it via sudo easy_install virtualenv
, here’s why I don’t do it that way:
- installs with root permissions
- installs into the system /Library
- pip is more actively developed than Setuptools’
easy_install
- using the tools provided by Homebrew yields a more reliable Python environment
As you might have guessed by now, we’re going to use the tools provided by Homebrew to install the Python packages that we want to be globally available. When installing via Homebrew Python’s pip, packages will be installed to/usr/local/lib/python2.7/site-packages
, with binaries placed in /usr/local/bin
.
Version control (optional)
The first thing I pip-install is Mercurial. Since I have Mercurial repositories that I push to both Bitbucket and GitHub, I installMercurial and hg-git on all my systems:
pip install Mercurial hg-git
At a minimum, you’ll need to add a few lines to your .hgrc file in order to use Mercurial:
vim ~/.hgrc
The following lines should get you started; just be sure to change the values to your name and email address, respectively:
[ui]
username = YOUR NAME <address@example.com>
To test whether Mercurial is configured and ready for use, run the following command:
hg debuginstall
If the last line in the response is “No problems detected”, then Mercurial has been installed and configured properly.
Virtualenv
Python packages installed via the steps above are global in the sense that they are available across all of your projects. That can be convenient at times, but it can also create problems. For example, sometimes one project needs the latest version of Django, while another needs Django 1.3 to retain compatibility with a critical third-party extension. This is one of many use cases that virtualenv was designed to solve. On my systems, only a handful of general purpose Python packages (such asMercurial and virtualenv) are globally available — every other package is confined to virtual environments.
With that explanation behind us, let’s install virtualenv:
pip install virtualenv
Create some directories to store our projects and virtual environments, respectively:
mkdir -p ~/Projects ~/Virtualenvs
We’ll then open the ~/.bashrc file…
vim ~/.bashrc
… and add some lines to it:
# pip should only run if there is a virtualenv currently activated
export PIP_REQUIRE_VIRTUALENV=true
# cache pip-installed packages to avoid re-downloading
export PIP_DOWNLOAD_CACHE=$HOME/.pip/cache
Let’s re-load our bash environment:
. ~/.bash_profile
Now we have virtualenv installed and ready to create new virtual environments, which we will store in ~/Virtualenvs
. New virtual environments can be created via:
cd ~/Virtualenvs
virtualenv foobar
If you have both Python 2.x and 3.x and want to create a Python 3.x virtualenv:
virtualenv -p python3 foobar-py3
… which makes it easier to switch between Python 2.x and 3.x foobar environments.
Restricting pip to virtual environments
What happens if we think we are working in an active virtual environment, but there actually is no virtual environment active, and we install something via pip install foobar
? Well, in that case the foobar
package gets installed into our global site-packages, defeating the purpose of our virtual environment isolation.
In an effort to avoid mistakenly pip-installing a project-specific package into my global site-packages, I previously usedeasy_install
for global packages and the virtualenv-bundled pip
for installing packages into virtual environments. That accomplished the isolation objective, since pip was only available from within virtual environments, making it impossible for me to pip install foobar
into my global site-packages by mistake. But easy_install
has some deficiences, such as the inability to uninstall a package, and I found myself wanting to use pip for both global and virtualenv packages.
Thankfully, pip has a sparsely-documented setting that tells it to bail if there is no active virtual environment, which is exactly what I want. In fact, we’ve already set that above, via the export PIP_REQUIRE_VIRTUALENV=true
directive. For example, let’s see what happens when we try to install a package in the absence of an activated virtual environment:
$ pip install markdown
Could not find an activated virtualenv (required).
Perfect! But once that option is set, how do we install or upgrade a global package? We can temporarily turn off this restriction by adding the following to your ~/.bashrc
:
syspip(){
PIP_REQUIRE_VIRTUALENV="" pip "$@"
}
If in the future we want to upgrade our global packages, the above function enables us to do so via:
syspip install --upgrade pip setuptools virtualenv
You could, of course, do the same via PIP_REQUIRE_VIRTUALENV="" pip install --upgrade foobar
, but that’s much more cumbersome to type.
Creating virtual environments
Let’s create a virtual environment for Pelican, a Python-based static site generator:
cd ~/Virtualenvs
virtualenv pelican
Change to the new environment and activate it via:
cd pelican
. bin/activate
To install Pelican into the virtual environment, we’ll use pip:
pip install pelican markdown
For more information about virtual environments, read the virtualenv docs.
Dotfiles
These are obviously just the basic steps to getting a Python development environment configured. If you found this useful, you might to also check out my dotfiles (GitHub mirror), which I recently started rebuilding from scratch. I’m still early in the process of selectively adding one building block at a time, with more to be added soon.
Thoughts?
Have a question or suggestion? Leave a comment below!