DEV Community

Anton Zhiyanov
Anton Zhiyanov

Posted on • Originally published at antonz.org

12 3

Automate your Python project with Makefile

When working on a library or application, certain tasks tend to show up over and over again:

  • checking the code with linters,
  • running tests with coverage,
  • deploying with Docker,
  • ...

JS developers are lucky (ha!): their package.json has a special scripts section for this stuff:

{
    ...
    "scripts": {
        "format": "prettier --write \"src/**/*.ts\"",
        "lint": "tslint -p tsconfig.json",
        "test": "jest --coverage --config jestconfig.json",
    },
    ...
}
Enter fullscreen mode Exit fullscreen mode

Nothing like this is provided with Python. You can, of course, make a .sh script for each task. But it litters the project directory, and it's better to keep all such tasks together. Installing a separate task runner or using the one built into IDE also seems weird.

Good news: Linux and macOS already have a great task automation tool for any project - Makefile.

Makefile for task automation

Perhaps you, like me, thought that Makefile is a relict from the 70s, useful for compiling C programs. True. But it is also perfectly suitable for automating any tasks in general.

Here's what it might look like in a python project. Create a file named Makefile:

coverage:  ## Run tests with coverage
    coverage erase
    coverage run --include=podsearch/* -m pytest -ra
    coverage report -m

deps:  ## Install dependencies
    pip install black coverage flake8 mypy pylint pytest tox

lint:  ## Lint and static-check
    flake8 podsearch
    pylint podsearch
    mypy podsearch

push:  ## Push code with tags
    git push && git push --tags

test:  ## Run tests
    pytest -ra
Enter fullscreen mode Exit fullscreen mode

And run linter with tests, for example:

$ make lint coverage

flake8 podsearch
pylint podsearch
...
mypy podsearch
...
coverage erase
coverage run —include=podsearch/* -m pytest -ra
...
coverage report -m
Name                    Stmts   Miss  Cover   Missing
-----------------------------------------------------
podsearch/__init__.py       2      0   100%
podsearch/http.py          17      0   100%
podsearch/searcher.py      51      0   100%
-----------------------------------------------------
TOTAL                      70      0   100%
Enter fullscreen mode Exit fullscreen mode

Features

Task steps

A task can include multiple steps, like lint in the example above:

lint:
    flake8 podsearch
    pylint podsearch
    mypy podsearch
Enter fullscreen mode Exit fullscreen mode

Each step is executed in a separate subprocess. To run a chain of actions (for example, cd and git pull) combine them through &&:

push:
    git push && git push --tags
Enter fullscreen mode Exit fullscreen mode

Task dependencies

Consider the test task, which should first perform linting, and then run the tests. Specify lint as a dependency for test, and you're done:

test: lint
    pytest -ra
Enter fullscreen mode Exit fullscreen mode

You can specify multiple space-separated dependencies. Or tasks can explicitly call each other:

lint:
    flake8 podsearch
    pylint podsearch
    mypy podsearch

test:
    pytest -ra

prepare:
    make lint
    make test
Enter fullscreen mode Exit fullscreen mode

Task parameters

Consider the serve task which serves a static site, with IP and port specified as parameters. No problem:

serve:
    python -m http.server dist --bind $(bind) $(port)
Enter fullscreen mode Exit fullscreen mode

Run task with parameters:

$ make serve bind=localhost port=3000
Enter fullscreen mode Exit fullscreen mode

You can specify default parameter values:

bind ?= localhost
port ?= 3000
serve:
    python -m http.server dist --bind $(bind) $(port)
Enter fullscreen mode Exit fullscreen mode

Now they are optional when running make:

$ make serve bind=192.168.0.1
$ make serve port=8000
$ make serve
Enter fullscreen mode Exit fullscreen mode

And so much more

If basic features are not enough, there are some great in-depth guides:

In the wild

Here is a Makefile from one of my projects (podcast search tool):

podsearch

Makefiles are great for automating routine tasks, regardless of the language you prefer. Use them!

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (1)

Collapse
 
jesseinit profile image
Jesse Egbosionu

Great and informative post. Learnt a thing or two.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay