Summary of Today’s Python Classroom: Your Project, Your Dependencies – Modules, Packages and Virtual Environments (10 Nov 2026)

Before we build the calculator from Saturday’s design, the project needs a proper home. Today was about structure and dependencies: the unglamorous part every real project depends on.

1. Where We’re Headed

The calculator will demonstrate the Open/Closed Principle: a class should be open for extension but closed for modification. We’ll build it twice, once in a way that breaks the principle and once in a way that follows it, so you can see the difference rather than take it on trust.

First, the groundwork.

2. Modules and Packages

What it isExample
ModuleAny single .py filetest.py
PackageA folder of modules, usually with an __init__.pymy_math/
project/
├── main.py
└── my_math/
    ├── __init__.py
    ├── utils.py
    └── geometry/
        ├── __init__.py
        └── utils.py

Importing:

import main_helpers                     # a module beside the one you're running
from my_math.utils import calculator    # dot notation, through the package
from my_math.geometry import utils      # a different utils.py, no clash
  • Dot notation follows the folder path.
  • Two modules can share a name if they live in different packages. my_math/utils.py and my_math/geometry/utils.py don’t collide.

About __init__.py: it marks a folder as a package and can run setup code when the package is imported. Since Python 3.3, a folder without one can still be imported (a “namespace package”), but add the file anyway. It makes your intent explicit and avoids confusing edge cases.

3. Two Kinds of Project

TypeYou build it toExamples
ApplicationRun itA CLI tool, a web app
LibraryLet other code import itAn SDK, a framework

4. Where Libraries Come From

  • The standard library ships with Python. Modules such as os, json and sqlite3 are just there.
  • External packages live on PyPI, the Python Package Index: boto3 for AWS, FastAPI, LangChain, and hundreds of thousands more.

5. Why Virtual Environments Exist

Install everything system-wide and projects start fighting.

Project A needs version 1 of a library. Project B needs version 2. You upgrade for B, and A breaks, even though you never touched A.

A virtual environment gives each project its own private set of packages. Upgrading one project can’t break another.

Create one:

python -m venv .venv

Activate it:

ShellCommand
Linux / Macsource .venv/bin/activate
Windows, Command Prompt.venv\Scripts\activate
Windows, PowerShell.venv\Scripts\Activate.ps1

PowerShell blocks scripts by default. If activation fails, run this once, then try again:

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Once it’s active, pip install puts packages inside .venv, and the system Python is untouched. Your prompt usually shows (.venv) so you know where you are.

6. Sharing a Project: requirements.txt

Never share .venv itself. It’s large, and it’s built for your operating system; it won’t work on someone else’s machine. Add it to .gitignore so it can’t be committed by accident:

.venv/

Share the list of dependencies instead:

pip freeze > requirements.txt       # record what's installed
pip install -r requirements.txt     # recreate it on another machine

Something to know about pip freeze: it records everything in the environment, including the dependencies of your dependencies and anything you installed to try out. That’s why the file is often longer than expected. It reproduces the environment exactly, but it doesn’t tell you which packages you actually chose.

7. pip vs uv

pipuv
Written inPythonRust
SpeedStandardMuch faster
Installs packagesYesYes
Creates virtual environmentsWith venvYes, built in
Installs Python itselfNoYes
Records dependenciesrequirements.txtpyproject.toml plus a lockfile, uv.lock

You’ve already used uv. The MCP and agents projects were set up with uv init and uv add, which is why they have pyproject.toml and uv.lock rather than requirements.txt. Today explained what uv was doing for you behind the scenes.

✅ Action Items

  1. Create a project with a package, two sub-packages and two modules that share a name. Import both from main.py.
  2. Make a virtual environment, activate it, install one package from PyPI, and confirm it isn’t visible from your system Python.
  3. Generate requirements.txt, delete .venv, recreate it, and reinstall from the file.
  4. Add .venv/ to .gitignore.
  5. Do the same with uv: uv init, uv add, and compare the files it creates with what pip gave you.

⏭️ Next up: the calculator, novice version first, inside a proper project.

By continuous learner

enthusiastic technology learner

Leave a comment