Modules Data And Errors
Modules, Packages & Virtual Environments
A module is simply a .py file — any Python file can be imported and reused in another.
Jr Codex Python Notes
Level: Intermediate Prerequisites: Module 2: Functions & Functional Basics Time to complete: ~25 minutes
Table of Contents
- What is a Module?
- Import Styles
- The Standard Library — A Quick Tour
- Packages
- Installing Third-Party Packages with
pip - Virtual Environments
if __name__ == "__main__"- Summary & Next Steps
1. What is a Module?
A module is simply a .py file — any Python file can be imported and reused in another.
# math_utils.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
PI = 3.14159# main.py
import math_utils
print(math_utils.add(3, 4)) # 7
print(math_utils.PI) # 3.14159Splitting code into modules is how real projects stay organized once they grow past a single script — a pattern every later module in this curriculum assumes you already know.
2. Import Styles
import math_utils # import the whole module, access via math_utils.add()
from math_utils import add # import ONE name directly, use add() directly
from math_utils import add, subtract # import MULTIPLE names
from math_utils import add as addition # rename on import
import math_utils as mu # rename the whole module
from math_utils import * # import EVERYTHING — avoid this (see below)| Style | When to Use |
|---|---|
import module | Default, safest — makes the source of each name explicit (module.func) |
from module import name | When you use name very frequently and the module is unambiguous |
import module as alias | Convention for well-known libraries (import numpy as np) |
from module import * | Avoid — pollutes your namespace, unclear where names came from |
# Why `import *` is discouraged:
from math_utils import *
from other_utils import *
# If both modules define `add`, which one wins? Unclear without checking both files.3. The Standard Library — A Quick Tour
Python ships with a huge collection of built-in modules — "batteries included." A few you'll use constantly:
import math
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.14159...
import random
print(random.randint(1, 10)) # random int between 1 and 10
print(random.choice(["a", "b", "c"])) # random item from a list
import datetime
today = datetime.date.today()
print(today) # e.g. 2026-07-03
import os
print(os.getcwd()) # current working directory
print(os.listdir(".")) # list files in current directory
import sys
print(sys.version) # Python version info| Module | Common Use |
|---|---|
math | Mathematical functions and constants |
random | Random number generation, shuffling, sampling |
datetime | Dates, times, durations |
os | Filesystem paths, environment variables, directories |
sys | Interpreter internals, command-line args, exit codes |
json | Parsing/writing JSON (Chapter 3) |
re | Regular expressions |
4. Packages
A package is a directory of modules, identified by containing an __init__.py file (can be empty).
my_package/
├── __init__.py
├── math_utils.py
└── string_utils.py
from my_package import math_utils
from my_package.string_utils import capitalize_words
math_utils.add(2, 3)Every third-party library you'll use later (NumPy, pandas, transformers) is distributed as a package exactly like this — understanding this structure demystifies what import numpy as np is actually doing.
5. Installing Third-Party Packages with pip
pip is Python's package installer, pulling from PyPI (the Python Package Index).
pip install requests # install the latest version
pip install requests==2.31.0 # install a specific version
pip install --upgrade requests # upgrade to latest
pip uninstall requests # remove a package
pip list # see installed packages
pip show requests # see details about one packageimport requests
response = requests.get("https://api.github.com")
print(response.status_code) # 200requirements.txt — Sharing Dependencies
Real projects list their dependencies in a file so others (or future you) can recreate the exact environment:
# requirements.txt
requests==2.31.0
numpy==1.26.0
pandas==2.1.0
pip install -r requirements.txt # installs everything listed
pip freeze > requirements.txt # generate the file from what's currently installed6. Virtual Environments
Installing packages globally on your machine causes a classic problem: Project A needs requests==2.0, Project B needs requests==2.31, and they conflict. A virtual environment gives each project its own isolated set of installed packages.
# Create a virtual environment (creates a "venv" folder)
python -m venv venv
# Activate it
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Your prompt now shows (venv) — installs are isolated to this project
(venv) $ pip install requests
# Deactivate when done
(venv) $ deactivateWithout a Virtual Environment With a Virtual Environment
───────────────────────────── ─────────────────────────────
Project A ──┐ Project A → venv_a (requests 2.0)
Project B ──┼─→ ONE global Python Project B → venv_b (requests 2.31)
Project C ──┘ (version conflicts!) Project C → venv_c (own packages)
───────────────────────────── ─────────────────────────────
Best practice: create a virtual environment for every project, and never commit the venv/ folder to version control (add it to .gitignore — only requirements.txt should be tracked).
7. if __name__ == "__main__"
You've seen this pattern since Chapter 1's first program — now the mechanism behind it:
# math_utils.py
def add(a, b):
return a + b
print(f"math_utils loaded, __name__ = {__name__}")
if __name__ == "__main__":
print("Running math_utils.py directly")
print(add(2, 3))$ python math_utils.py
math_utils loaded, __name__ = __main__
Running math_utils.py directly
5# main.py
import math_utils # math_utils's print() runs, but __name__ is "math_utils" here, NOT "__main__"$ python main.py
math_utils loaded, __name__ = math_utilsWhy this matters: it lets a file work both as an importable module and a standalone script — code inside the if __name__ == "__main__": block only runs when the file is executed directly, never when it's imported elsewhere.
8. Summary & Next Steps
Key Takeaways
- A module is any
.pyfile; a package is a directory of modules with an__init__.py. - Prefer
import moduleorfrom module import specific_name— avoidfrom module import *, which hides where names come from. pipinstalls third-party packages from PyPI;requirements.txtrecords exact versions for reproducibility.- Always use a virtual environment per project — it isolates dependencies and avoids version conflicts between projects.
if __name__ == "__main__":lets a file act as both a reusable module and a standalone script.
Concept Check
- Why is
from module import *generally discouraged? - What problem do virtual environments solve?
- What does
__name__equal when a file is run directly vs. imported by another file?
Next Chapter
Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index