Python Full Tutorial -- Part 10: Modules & Packages

By Suraj Ahir 2026-01-06 11 min read

← Part 9Python Tutorial · Part 10 of 12Part 11 →
Python Full Tutorial -- Part 10: Modules & Packages

Python's module and package system is one of its greatest strengths. The standard library covers an enormous range of tasks with no extra installation. The PyPI ecosystem adds hundreds of thousands more packages. Understanding how to organise your own code into modules and how to use pip effectively is essential professional Python knowledge.

Creating and Importing Modules

Module basics
# utils.py
def calculate_tax(amount, rate=0.18):
    return amount * rate

SUPPORTED_CURRENCIES = ["INR", "USD", "EUR"]

# main.py
import utils
tax = utils.calculate_tax(1000)       # 180.0

from utils import calculate_tax
tax = calculate_tax(1000, rate=0.28)  # 280.0

import utils as u
print(u.SUPPORTED_CURRENCIES)

Package Structure

Organising code into a package
myapp/
    __init__.py          # Marks directory as package
    models/
        __init__.py
        user.py
        product.py
    services/
        __init__.py
        payment.py
    utils/
        validators.py
    main.py
Import from package
from myapp.models.user import User
from myapp.services.payment import process_payment
from myapp.utils import validators

Standard Library Highlights

Essential standard library modules
import os, sys, json, re, datetime
from pathlib import Path
from collections import Counter, defaultdict
import logging

# os
os.makedirs("logs", exist_ok=True)
files = os.listdir(".")
env_var = os.environ.get("HOME", "/tmp")

# datetime
now = datetime.datetime.now()
formatted = now.strftime("%Y-%m-%d %H:%M")
tomorrow = now + datetime.timedelta(days=1)

# re (regular expressions)
pattern = r"^[\w.-]+@[\w.-]+\.\w+$"
print(bool(re.match(pattern, "suraj@example.com")))  # True

Virtual Environments and pip

Project dependency management
# Create virtual environment
python3 -m venv venv
source venv/bin/activate        # Linux/macOS
.\venv\Scripts\activate         # Windows

# Install packages in venv
pip install requests flask pandas pytest

# Save dependencies
pip freeze > requirements.txt

# Install from file
pip install -r requirements.txt

# Useful commands
pip list                   # List installed
pip show requests          # Info about package
pip install --upgrade pip  # Update pip itself

Frequently Asked Questions

Module vs package?

A module is a single .py file. A package is a directory with __init__.py containing multiple modules. Both are imported the same way.

How does Python find modules?

Python searches: sys.modules cache, built-in modules, then sys.path directories. sys.path includes current directory and site-packages where pip installs.

How do I install packages?

pip install package-name. Specific version: pip install requests==2.28. From file: pip install -r requirements.txt. Always use a virtual environment.

What is the standard library?

Modules included with every Python installation -- no pip needed. Covers os, sys, json, csv, datetime, re, pathlib, logging, threading, http, unittest, and hundreds more.

Why use virtual environments?

Each project gets its own isolated Python and packages. Prevents version conflicts between projects. Without venvs, all projects share one global Python and conflicts are inevitable.

In Part 11, we cover Object-Oriented Programming -- classes, inheritance, and the OOP patterns used in major Python frameworks.

Key takeaways

Continue reading
Part 11 — Testing and Debugging
Code that doesn't break (often).
Suraj Ahir — author of SRJahir Tech

Written by

Suraj Ahir

Cloud & DevOps engineer running four live production services on my own AWS infrastructure. I write everything on this site myself — no ghostwriters, no AI filler.

← Part 9Python Tutorial · Part 10 of 12Part 11 →
← Back to Blog
Disclaimer: Educational content only. No guarantees of outcome.

Virtual Environments with pyenv

Managing Python versions with pyenv
# Install pyenv (manages multiple Python versions)
curl https://pyenv.run | bash

# Install Python versions
pyenv install 3.11.8
pyenv install 3.12.2

# Set default globally
pyenv global 3.11.8

# Set per project
cd myproject
pyenv local 3.12.2   # Creates .python-version file

# Create virtual environment with specific version
pyenv local 3.12.2
python -m venv venv
source venv/bin/activate

Project Management with Poetry

Modern Python dependency management
pip install poetry

# Create new project
poetry new myproject
cd myproject

# Add dependencies
poetry add flask requests boto3
poetry add --group dev pytest black mypy

# pyproject.toml manages everything
[tool.poetry.dependencies]
python = "^3.11"
flask = "^3.0"
requests = "^2.31"

# Install all dependencies
poetry install

# Run commands in virtual env
poetry run python app.py
poetry run pytest

# Export to requirements.txt for compatibility
poetry export -f requirements.txt --output requirements.txt

Module Best Practices for Large Projects

Organising Python code professionally
myapp/
    __init__.py          # Keep minimal: just expose public API
    config.py            # Configuration constants
    models/
        __init__.py      # from .user import User (re-export)
        user.py
        order.py
    services/
        __init__.py
        email_service.py
        payment_service.py
    utils/
        __init__.py
        validators.py
        formatters.py
    tests/
        conftest.py      # Shared pytest fixtures
        test_models.py
        test_services.py
__init__.py pattern for clean imports
# models/__init__.py
from .user import User
from .order import Order, OrderStatus
from .product import Product

__all__ = ["User", "Order", "OrderStatus", "Product"]

# Now users can do:
from myapp.models import User, Order   # Clean import
# Instead of:
from myapp.models.user import User      # Exposes internal structure

Import System Deep Dive

How Python imports work
import sys

# See where Python looks for modules
print(sys.path)
# ['', '/usr/lib/python3.11', '/usr/lib/python3.11/lib-dynload',
#  '/home/suraj/.local/lib/python3.11/site-packages', ...]

# Add a directory to search path
sys.path.insert(0, '/home/suraj/mylibs')

# See all cached (already imported) modules
print(list(sys.modules.keys())[:10])

# Reload a module after changing it (useful in REPL)
import importlib
importlib.reload(mymodule)

# Conditional imports
try:
    import ujson as json  # Faster JSON if available
except ImportError:
    import json           # Fall back to stdlib

# Lazy imports for startup performance
def get_pandas():
    import pandas as pd   # Only imported when first called
    return pd

Creating Executable Python Scripts

CLI tools with argparse
#!/usr/bin/env python3
"""
disk-check: Check disk usage and alert if above threshold.
Usage: disk-check --threshold 85 --path /
"""
import argparse
import sys
import shutil

def check_disk(path: str, threshold: int) -> int:
    total, used, free = shutil.disk_usage(path)
    pct = (used / total) * 100
    
    print(f"Path: {path}")
    print(f"Total: {total / 1e9:.1f} GB")
    print(f"Used:  {used  / 1e9:.1f} GB ({pct:.1f}%)")
    print(f"Free:  {free  / 1e9:.1f} GB")
    
    if pct >= threshold:
        print(f"ALERT: Disk usage {pct:.1f}% exceeds threshold {threshold}%")
        return 1
    return 0

def main():
    parser = argparse.ArgumentParser(description="Check disk usage")
    parser.add_argument("--path",      default="/",  help="Path to check")
    parser.add_argument("--threshold", type=int, default=85, help="Alert %")
    args = parser.parse_args()
    sys.exit(check_disk(args.path, args.threshold))

if __name__ == "__main__":
    main()