Module 08

So you want to package your Python code

Once a script becomes useful twice, it has usually earned the right to stop living as `final_really_final_v3.py`.

Estimated time: 35 to 50 min Prerequisite: comfort with terminal basics

Why package your analysis code

Researchers often begin with one-off scripts. That is a perfectly good starting point, but once code is reused across experiments or passed to someone else, a package structure helps reduce confusion.

Packaging encourages clearer function names, tests, documented dependencies, and a layout that collaborators can navigate.

For many researchers the real benefit is reliability: a package gives you a structure you can return to later without rebuilding the project from memory.

Install cookiecutter

Inside a fresh environment, install the template generator:

python -m pip install cookiecutter
python -m pip show cookiecutter

Generate a project from the HenriquesLab template

Use the cookiecutter template referenced for this course:

cookiecutter gh:HenriquesLab/PythonPackageCookiecutter

Cookiecutter will prompt you for a project name, package name, author information, and other setup values. Answer carefully, because these values shape the generated files.

If the prompts feel abstract, slow down and answer them one at a time. This is one of the places where thoughtful setup saves confusion later.

What to explain while teaching

  • Project name: the human-readable repo or folder name.
  • Package name: the Python import name, usually lowercase with underscores.
  • Version: a starting release label, often 0.1.0.
  • Description: one sentence on what the package does for a researcher.

Explore the generated structure

After the template runs, walk learners through the top-level files and folders. Focus on what each one does instead of listing every file mechanically.

  1. The package folder holds the reusable Python code.
  2. The tests folder is where you check that functions still behave correctly.
  3. The project metadata files record dependencies and packaging details.
  4. The README becomes the landing page for collaborators and future-you.

The point is not to memorise every generated file immediately. The point is to understand the role of the main pieces.

Add one simple analysis function

A good first package function is small and concrete, such as normalising an intensity measurement or summarising per-cell values.

def mean_signal(values):
    """Return the arithmetic mean of a list of measurements."""
    return sum(values) / len(values)

Then add a tiny test using a known input and expected output.

A deliberately small function is ideal here. You are learning the project structure, not trying to solve your whole analysis problem at once.

Minimal test example

from your_package_name.module import mean_signal


def test_mean_signal():
    assert mean_signal([2, 4, 6]) == 4

Example package layout to point out

your-project/
├── README.md
├── pyproject.toml
├── src/
│   └── your_package_name/
│       ├── __init__.py
│       └── module.py
└── tests/
    └── test_module.py

Suggested exercise

  1. Create a package for a small image-analysis helper toolkit.
  2. Add one function that operates on a list of measurements.
  3. Write one test for that function.
  4. Write two sentences in the README describing the biological use case.

Stop here for today if needed

A natural stopping point is right after generating the project and understanding the top-level folders. The next session can focus on adding one function and one test.

Important note

This lesson uses the template path supplied for the course: gh:HenriquesLab/PythonPackageCookiecutter. If the repository name changes later, update the command in this page so learners do not hit a dead end.

Where to go next

By this point, learners have a complete beginner workflow: local Python, isolated environments, notebooks for exploration, napari for visual inspection, and a package template for reusable code.

A strong follow-up project would be to choose one small real workflow from the lab and turn it into a notebook plus a few reusable functions inside a package.