THE FUTURE MARKETACADEMY
Your classroomRoom 07 · Tech Lab
School of Data & Tech

Python Projects: testing, packaging and version control

Step 7 of 8 in Tech Lab

Next in your path: 7.6.3 Site Systems: bookings, payments and integrations

What you'll be able to do
  • Split a program into modules and a package with a clear, standard folder layout.
  • Handle errors on purpose: your own exception classes, clear messages and correct exit codes.
  • Write automatic tests with pytest, including tests for errors and for files.
  • Track every change with git: commits, a good .gitignore, history and differences.
  • Work on branches, merge them, fix a merge conflict and understand pull requests.
  • Turn your project into an installable package with pyproject.toml and a command people can type.
  • Ship a release: version number, git tag, README, licence and a tested wheel file.

Before this course: Python for Data: files, libraries and automation (course 7.5.2). You should already be able to use pathlib, read CSV and JSON, create a virtual environment, install packages with pip, write a requirements.txt and build a small script with argparse and logging. If those are new, take 7.5.2 first. This course does not repeat them.

All through the course you build one small tool called ordertools. It reads an order file (a CSV with the columns product, qty and price) and prints the total. The tool is small on purpose, so you can focus on the project skills around it.

Every code example in this course was run and its output checked with Python 3.9, pytest 8.4.2 and git 2.50 on a Mac. Newer versions give the same results for these examples. On Windows, type py or python where the course says python3.

Words in this course 42Open the Vocabulary Hall
01

Modules, packages and a project layout

In simple words

A big program in one file is like a kitchen with every pot, spoon and plate in one drawer. Modules are separate drawers, each with one kind of thing. A package is a cupboard full of labelled drawers, and the project layout is the plan of the whole kitchen, so anyone can find anything.

Key facts
  • A module is any .py file. Another file can use it with import prices or from prices import with_tax.
  • A module's code runs once, the first time it is imported in a program.
  • Every module has a name in __name__. When you run a file directly, its __name__ is "__main__". When it is imported, __name__ is the module's name. So code inside if __name__ == "__main__": runs only when you run the file itself, not when someone imports it.
  • A package is a folder of modules. The Python Packaging User Guide recommends an __init__.py file in it (it can be empty), so the folder imports as a regular package.
  • The packaging tutorial uses the src layout: your package folder sits inside a folder called src, next to pyproject.toml, README.md, LICENSE and a tests folder.
  • A file called __main__.py inside a package lets people run the package with python3 -m packagename.
  • Good habit: keep the logic (calculations, checks) in one module with no printing and no input(), and keep the interface (argparse, printing) in another module. Logic without printing is much easier to test (Lesson 3).

The ordertools layout:

ordertools/
├── pyproject.toml    (Lesson 6)
├── README.md
├── LICENSE
├── .gitignore      (Lesson 4)
├── src/
│  └── ordertools/
│    ├── __init__.py  (holds __version__ = "0.1.0")
│    ├── __main__.py  (lets you run python3 -m ordertools)
│    ├── core.py    (the logic)
│    └── cli.py    (the command line)
└── tests/
  ├── test_core.py
  └── test_cli.py
Example (tested): two modules

prices.py:

"""Helpers for prices."""
TAX_RATE = 0.10


def with_tax(price, rate=TAX_RATE):
  return round(price * (1 + rate), 2)


print("prices.py: __name__ is", __name__)

if __name__ == "__main__":
  print("Running prices.py directly:", with_tax(20))

shop.py:

import prices
from prices import with_tax

print(prices.TAX_RATE, with_tax(50), with_tax(50, rate=0.05))

Run python3 prices.py: it prints prices.py: __name__ is __main__ and Running prices.py directly: 22.0. Run python3 shop.py: it prints prices.py: __name__ is prices (only once, even though shop.py imports prices twice) and 0.1 55.0 52.5. The "Running directly" line does not appear, because prices.py was imported, not run.

Step by step
  1. Make a folder called l1, save prices.py and shop.py in it exactly as shown.
  2. Run python3 prices.py and read the two lines.
  3. Run python3 shop.py and compare: which line disappeared, and why?
  4. Now make the real project folders: ordertools/src/ordertools and ordertools/tests.
  5. Inside src/ordertools create an __init__.py with one line: __version__ = "0.1.0".
  6. Create empty files core.py, cli.py and __main__.py next to it. You fill them in Lessons 2 and 6.
  7. Check: your folders match the layout above, and you can explain in one sentence what if __name__ == "__main__": does.
Watch on YouTube
Python tutorial: if __name__ == '__main__'Corey Schafer · YouTube · youtube.com

Videos by other creators on YouTube, for reference. They are not made by or affiliated with The Future Market.

LESSON 01Modules, packages and a project layout
LESSON 01 / ANIMATED LESSON / AI VOICE00:00 / 01:00
Read the video script
[Host] "One giant file is a messy kitchen. Let's give everything a drawer."
[Screen: prices.py and shop.py side by side] "A module is just a py file. Import it, and you can use its functions."
[Screen: terminal showing __name__ is __main__, then __name__ is prices] "Run a file directly and its name is main. Import it, and its name is the module name. That's why the main check works."
[Screen: the ordertools folder tree with src and tests] "A package is a folder of modules. Put it in src, tests next to it, and keep logic apart from printing."
Try it now

Add a third module labels.py to the l1 folder with a function money(x) that returns text like $12.50. Import it in shop.py and print money(with_tax(50)). Add a if __name__ == "__main__": block to labels.py that prints a quick self-check, and prove it does not run when shop.py imports it.

ClaudeStuck? Copy a ready-made prompt for Claude

Copy this, open Claude, paste it, and Claude will walk you through the lesson step by step.

For a grown-up: Claude is for adults (18+). Copy this, paste it into Claude, and use the answer to explain the lesson to your child.

I'm learning "Python Projects: testing, packaging and version control" on The Future Market. Lesson 1: "Modules, packages and a project layout".

What the lesson teaches:
- A module is any .py file. Another file can use it with import prices or from prices import with_tax.
- A module's code runs once, the first time it is imported in a program.
- Every module has a name in __name__. When you run a file directly, its __name__ is "__main__". When it is imported, __name__ is the module's name. So code inside if __name__ == "__main__": runs only when you run the file itself, not when someone imports it.
- A package is a folder of modules. The Python Packaging User Guide recommends an __init__.py file in it (it can be empty), so the folder imports as a regular package.
- The packaging tutorial uses the src layout: your package folder sits inside a folder called src, next to pyproject.toml, README.md, LICENSE and a tests folder.
- A file called __main__.py inside a package lets people run the package with python3 -m packagename.
- Good habit: keep the logic (calculations, checks) in one module with no printing and no input(), and keep the interface (argparse, printing) in another module. Logic without printing is much easier to test (Lesson 3).

The exercise I'm working on:
Add a third module labels.py to the l1 folder with a function money(x) that returns text like $12.50. Import it in shop.py and print money(with_tax(50)). Add a if __name__ == "__main__": block to labels.py that prints a quick self-check, and prove it does not run when shop.py imports it.

I'm stuck. Please:
1. Explain the main idea in plain, simple words with one everyday example.
2. Walk me through the exercise one small step at a time. Ask me what I've done so far before giving the next step.
3. Don't just give me the final answer. Help me do it myself, and check my work when I share it.
I'm a parent helping my child (about 8 years old) with a lesson called "Modules, packages and a project layout" from the course "Python Projects: testing, packaging and version control".

Here's what the lesson says:
A big program in one file is like a kitchen with every pot, spoon and plate in one drawer. Modules are separate drawers, each with one kind of thing. A package is a cupboard full of labelled drawers, and the project layout is the plan of the whole kitchen, so anyone can find anything.

The activity:
Add a third module labels.py to the l1 folder with a function money(x) that returns text like $12.50. Import it in shop.py and print money(with_tax(50)). Add a if __name__ == "__main__": block to labels.py that prints a quick self-check, and prove it does not run when shop.py imports it.

Please explain this so an 8-year-old understands: short sentences, a fun everyday example, and no hard words.
Then give me 3 simple questions I can ask my child to check they understood, and a way to do the activity together, one tiny step at a time.
Open Claude
Sources
My notes
02

Errors on purpose: exceptions, messages and exit codes

This lesson is part of full access: every course and every level for one payment.

03

Automatic tests with pytest

This lesson is part of full access: every course and every level for one payment.

04

Track every change with git

This lesson is part of full access: every course and every level for one payment.

05

Branches, merges and pull requests

This lesson is part of full access: every course and every level for one payment.

06

Packaging with pyproject.toml

This lesson is part of full access: every course and every level for one payment.

07

Ship it: versions, tags and a release others can install

This lesson is part of full access: every course and every level for one payment.

++

Final project

This lesson is part of full access: every course and every level for one payment.

??

Quiz

  1. What does if __name__ == "__main__": do?

  2. Why keep logic and printing in separate modules?

  3. When does the else part of a try statement run?

  4. What does raise NewError(...) from exc add?

  5. What exit code means a command-line tool succeeded?

  6. Which files and functions does pytest run automatically?

  7. How do you test that a function raises an error?

  8. What does git diff --staged show?

  9. Name two things that should be in .gitignore for a Python project.

  10. What do you do to finish a merge conflict?

  11. What does ordertotal = "ordertools.cli:main" under [project.scripts] do?

  12. In semantic versioning, which number changes for a new feature that breaks nothing?

EX

Final exam

This lesson is part of full access: every course and every level for one payment.

CE

Certificate

This lesson is part of full access: every course and every level for one payment.