Stage 1 of 10 · 8 lessons · ~4 weeks
From notebook to package
See the whole lifecycle once, then turn notebook code into a Python project with a proper layout, locked dependencies, config outside the code, tests and a container image.
Start: The lifecycle and the tool mapLessons· one lesson for each topic, in this order
- 1The lifecycle and the tool mapLesson
- 2Why notebook code breaks in productionLesson
- 3Project layout and pyproject.tomlLesson
- 4Dependencies and lockfiles with uvLesson
- 5Config and secrets outside the codeLesson
- 6One command to train, and a saved pipelineLesson
- 7Tests for ML codeLesson
- 8Containerise the projectLesson
Do this
- Move notebook code into a src package with one module per job.
- Declare dependencies in pyproject.toml and commit uv.lock.
- Move paths and settings to a config file and secrets to environment variables.
- Add pytest tests for feature or prompt-building code plus one smoke test.
- Make training or the LLM feature run with a single command.
- Build a Docker image and run the command inside it.
Start with· follow one of these
- CoursePaidGrokking Python Fundamentals
Design Gurus · Beginner · $50
If your Python stops at notebooks: modules, functions, classes and error handling done properly
- CourseFreeMade With ML
Goku Mohandas · Advanced
Free: the scripting, CLI, testing and documentation lessons turn notebook code into a real project
Practise
Keep handy
Also worth your time
Before moving on: A Git repository where your notebook code lives in a src package with pyproject.toml and uv.lock, config in a file, secrets in environment variables, passing pytest tests, and a Docker image that trains the model or runs the LLM feature with one command.

This stage feels like housekeeping, and it is the one most ML learners skip. Do it properly once and every later stage gets easier, because pipelines, CI and serving all assume code that installs cleanly and runs with one command. Keep your notebooks, but make them import from the package.