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`.
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.
- The package folder holds the reusable Python code.
- The tests folder is where you check that functions still behave correctly.
- The project metadata files record dependencies and packaging details.
- 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
- Create a package for a small image-analysis helper toolkit.
- Add one function that operates on a list of measurements.
- Write one test for that function.
- 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.