Python Project Makefile with Virtual Environment

Build a Makefile for Python projects managing virtual environments, pip dependencies, testing with pytest, linting with flake8/mypy, and packaging.

Language-Specific

Detailed Explanation

Python Development with Make

Python projects benefit enormously from Makefiles. Virtual environment creation, dependency installation, linting, testing, and packaging all become single commands.

Virtual Environment Management

PYTHON  ?= python3
VENV    = .venv
BIN     = $(VENV)/bin

$(VENV)/bin/activate: requirements.txt
	$(PYTHON) -m venv $(VENV)
	$(BIN)/pip install --upgrade pip
	$(BIN)/pip install -r requirements.txt
	@touch $(VENV)/bin/activate

venv: $(VENV)/bin/activate

This target tracks requirements.txt as a dependency. The virtual environment is only recreated when requirements change. The @touch ensures the activation script's modification time is updated for accurate dependency checking.

Testing and Linting

test: venv
	$(BIN)/python -m pytest tests/ -v --cov=src --cov-report=html

lint: venv
	$(BIN)/python -m flake8 src/ tests/
	$(BIN)/python -m mypy src/
	$(BIN)/python -m black --check src/ tests/

format: venv
	$(BIN)/python -m black src/ tests/
	$(BIN)/python -m isort src/ tests/

All tools run from the virtual environment, ensuring consistent versions. The lint target chains multiple checks — if any fails, the subsequent ones do not run.

Packaging

dist: venv
	$(BIN)/python -m build

publish: dist
	$(BIN)/python -m twine upload dist/*

Build a wheel and source distribution, then upload to PyPI. The publish target depends on dist, ensuring the package is built first.

Development Workflow

run: venv
	$(BIN)/python src/main.py

shell: venv
	$(BIN)/ipython

clean:
	rm -rf $(VENV) dist build *.egg-info .pytest_cache .mypy_cache htmlcov
	find . -name '*.pyc' -delete
	find . -name '__pycache__' -type d -exec rm -rf {} +

The clean target removes the virtual environment, build artifacts, and all compiled Python files (.pyc).

Best Practices

  • Always use $(BIN)/python instead of activating the venv, so Make commands work without sourcing activate
  • Pin exact dependency versions in requirements.txt for reproducibility
  • Separate development dependencies into requirements-dev.txt

Use Case

Managing a Python library or application where you need reproducible virtual environment setup, automated testing with coverage, type checking with mypy, and one-command packaging for PyPI.

Try It — Makefile Generator

Open full tool