Comparing Python Project Scaffolding and Build Tools: Cookiecutter, PyScaffold, PyBuilder, and Poetry
This article reviews the lack of a standard Python project structure and compares four popular scaffolding and build tools—Cookiecutter, PyScaffold, PyBuilder, and Poetry—detailing their installation, generated directory layouts, and typical make/ tox/ poetry commands for testing, documentation, and packaging.
Python has long lacked a de‑facto standard project management and build tool, resulting in many different project structures and build processes. This flexibility reflects Python's "freedom of choice" philosophy.
Unlike Java, which evolved from manual builds to Ant, then Maven (which became the de‑facto standard despite challenges from Gradle, SBT, Ivy, etc.), Python's ecosystem provides package managers such as pip, pipenv, and conda but no enforced directory layout.
Traditional Python builds still rely on Makefiles, setup.py , or build.py , and various template‑based tools exist to generate project skeletons.
Cookiecutter – a classic Python project layout
<code>$ pip install cookiecutter
$ cookiecutter gh:audreyr/cookiecutter-pypackage # use the GitHub template to answer prompts and generate a project
project_name [Python Boilerplate]: sample
</code>The generated project looks like:
<code>$ tree sample
sample
├── AUTHORS.rst
├── CONTRIBUTING.rst
├── HISTORY.rst
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.rst
├── docs
│ ├── Makefile
│ ├── authors.rst
│ ├── conf.py
│ ├── contributing.rst
│ ├── history.rst
│ ├── index.rst
│ ├── installation.rst
│ ├── make.bat
│ ├── readme.rst
│ └── usage.rst
├── requirements_dev.txt
├── sample
│ ├── __init__.py
│ ├── cli.py
│ └── sample.py
├── setup.cfg
├── setup.py
├── tests
│ ├── __init__.py
│ └── test_sample.py
└── tox.ini
</code>Key elements are the sample package for source code, a tests directory for unit tests, a docs folder for documentation, and standard build files ( setup.py , setup.cfg , Makefile ).
Building the project can be driven by make commands such as make test , make coverage , make docs , and make dist . Required tools (e.g., tox , wheel , coverage , sphinx , flake8 ) are installed via pip .
PyScaffold – creating a project
PyScaffold is a scaffolding tool that places source files under a src directory.
<code>$ pip install pyscaffold
$ putup sample
</code>The resulting layout is similar to Cookiecutter but with src :
<code>$ tree sample
sample
├── AUTHORS.rst
├── CHANGELOG.rst
├── CONTRIBUTING.rst
├── LICENSE.txt
├── README.rst
├── docs
│ ├── Makefile
│ ├── _static
│ ├── authors.rst
│ ├── changelog.rst
│ ├── conf.py
│ ├── contributing.rst
│ ├── index.rst
│ ├── license.rst
│ ├── readme.rst
│ └── requirements.txt
├── pyproject.toml
├── setup.cfg
├── setup.py
├── src
│ └── sample
│ ├── __init__.py
│ └── skeleton.py
├── tests
│ ├── conftest.py
│ └── test_skeleton.py
└── tox.ini
</code>Building and testing are performed with tox , which creates isolated virtual environments for each task.
<code>$ tox -av
default environments:
default -> Invoke pytest to run automated tests
additional environments:
build -> Build the package in isolation according to PEP517
clean -> Remove old distribution files and temporary artifacts
docs -> Invoke sphinx-build to build the documentation
...</code>PyBuilder
PyBuilder offers a Maven‑like structure and uses plugins defined in build.py .
<code>$ pip install pybuilder
$ mkdir sample && cd sample # create project directory manually
$ pyb --start-project # answer prompts to generate files
</code>Directory layout after generation:
<code>$ tree sample
.
├── build.py
├── docs
├── pyproject.toml
├── setup.py
└── src
├── main
│ ├── python
│ └── scripts
└── unittest
└── python
</code>Typical tasks are listed with pyb -t sample and include analyze , clean , compile_sources , test , package , publish , etc. Dependencies are declared in build.py and installed when the virtual environment is created.
Poetry
Poetry is a modern, actively maintained tool that focuses on dependency management and packaging.
<code>$ pip install poetry
$ poetry new sample
</code>Resulting layout (simplest form):
<code>$ tree sample
sample
├── README.rst
├── pyproject.toml
├── sample
│ └── __init__.py
└── tests
├── __init__.py
└── test_sample.py
</code>Adding the --src flag places source code under src . The pyproject.toml file serves a role similar to package.json in Node.js, holding all configuration, dependencies, and build settings.
<code># Add a dependency and install it
poetry add boto3
poetry install
# Build distribution files
poetry build
# Run tests
poetry run pytest
# Export requirements.txt
poetry export --without-hashes --output requirements.txt
</code>Custom scripts can be defined in pyproject.toml and executed with poetry run , e.g.:
<code>[tool.poetry.scripts]
my-script = "sample.my_module:main"
</code> <code>$ poetry run my-script
# prints "hello poetry"
</code>Overall, the complexity of generated project structures decreases from Cookiecutter → PyScaffold → PyBuilder → Poetry, roughly matching the learning curve for each tool.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.