Why are there no Makefiles for automation in Python projects?

There is a number of options for automation in Python. I don't think there is a culture against automation, there is just not one dominant way of doing it. The common denominator is distutils.

The one which is closed to your description is buildout. This is mostly used in the Zope/Plone world.

I myself use a combination of the following: Distribute, pip and Fabric. I am mostly developing using Django that has manage.py for automation commands.

It is also being actively worked on in Python 3.3


Setuptools can automate a lot of things, and for things that aren't built-in, it's easily extensible.

  • To run unittests, you can use the setup.py test command after having added a test_suite argument to the setup() call. (documentation)
  • Dependencies (even if not available on PyPI) can be handled by adding a install_requires/extras_require/dependency_links argument to the setup() call. (documentation)
  • To create a .deb package, you can use the stdeb module.
  • For everything else, you can add custom setup.py commands.

But I agree with S.Lott, most of the tasks you'd wish to automate (except dependencies handling maybe, it's the only one I find really useful) are tasks you don't run everyday, so there wouldn't be any real productivity improvement by automating them.


Actually, automation is useful to Python developers too!

Invoke is probably the closest tool to what you have in mind, for automation of common repetitive Python tasks: https://github.com/pyinvoke/invoke

With invoke, you can create a tasks.py like this one (borrowed from the invoke docs)

from invoke import run, task

@task
def clean(docs=False, bytecode=False, extra=''):
    patterns = ['build']
    if docs:
        patterns.append('docs/_build')
    if bytecode:
        patterns.append('**/*.pyc')
    if extra:
        patterns.append(extra)
    for pattern in patterns:
        run("rm -rf %s" % pattern)

@task
def build(docs=False):
    run("python setup.py build")
    if docs:
        run("sphinx-build docs docs/_build")

You can then run the tasks at the command line, for example:

$ invoke clean
$ invoke build --docs

Another option is to simply use a Makefile. For example, a Python project's Makefile could look like this:

docs:
    $(MAKE) -C docs clean
    $(MAKE) -C docs html
    open docs/_build/html/index.html

release: clean
    python setup.py sdist upload

sdist: clean
    python setup.py sdist
    ls -l dist