Yeah, with the previous four posts in this series you’re
bound to have a couple of released python packages. And several external
dependencies.

Where do you install them? System-wide just with easy_installxyz? What
about conflicting versions? One project needs django 1.0, another 1.1. And
networkx 0.99 deprecated a method that was still there in 0.7, so suddenly
your website doesn’t work anymore. Oh, and those 264 packages in your system
python are no fun.

The solution for these version management and isolated environment
problems is buildout.

Create a directory somewhere and download the so-called “bootstrap file”. I’m
showing instructions for a Linux prompt, but it works just as well on windows
(but you’ll have to make the translation to windows commands yourself):

Now you’ll need an almost-empty buildout to start with. Open up a text editor
and save the following as buildout.cfg

[buildout]
parts =

Run the bootstrap file. This only has to be done once. It makes sure the
basics (setuptools/distribute and buildout itself) are installed so that
buildout can actually run. “Bootstrapping”, you say? Yes.
Bootstrapping. The notorious Baron von Münchhausen once was stuck in a swamp
and pulled himself out of it by pulling at the straps at the back of his
boots. That’s where the name comes from.

After running the bootstrap you’ll have a bin/ directory with buildout
or buildout.exe (on windows) inside it. Run bin/buildout and you’ve
just run your first buildout (which didn’t do a bloody thing).

Most of the content in there is just the basic stuff that easy_install would
place there, too. Apart from the sys.path[0:0] line. The sys.path is
the path where python looks when importing a module (like pep8). And
sys.path[0:0] places the two items you assign to it (the location of the
pep8 and the distribute egg) right in front of everything else on that import
path. So an “import pep8” is guaranteed to find the pep8 package that
buildout installed for you first.

When you set up a website with buildout (grabbing django and a couple of
add-ons, for instance) and test it all locally (works fine) and later run the
same buildout on the server, you do not want it to crash because there’s a
newer version of one of the add-ons that isn’t compatible with the rest. You
want reliability.

When I deploy a buildout, I want the same rebuildability in my buildout as I
want in my packaged python code. So I want to tag them with
zest.releaser.

Normally, zest.releaser works with the version info from the setup.py, but
buildouts often don’t have such a file. Luckily, zest.releaser also looks for
a version.txt file. So put 0.1dev all by itself in a version.txt
right next to the buildout and you can use zest.releaser.

Deploying a website is so much more robust when the entire deployment is
simply an (svn-)tagged buildout directory with pinned package versions in it.
No surprises.

You won’t believe the speed with which colleagues get used to buildouts. Once
they’ve been pointed to an svn directory and got the instructions “just check
that out, run pythonbootstrap.py and bin/buildout”... They’ll never
want to get back to the 4-page instructions on how to collect all the bits and
pieces by hand.

Recipes are buildout’s way of extending itself. There are a lot of them.
Setting up cron jobs, downloading from svn/hg/git/bzr, setting up django,
etc. Browse through the huge number of recipes on pypi
for a while.

This tells buildout (ALL your buildouts) to store the eggs, downloads (and
configs, for those extends=http://some.zope.server/version12.cfg lines) in
those directories. Download once, use everywhere. Saves you a lot of time
when you have lots of similar projects.