📦 DevAscent Academy • Core Python Textbook Series

Unit 9: Modules and Packages

The definitive academic and industry guide to modular Python architecture. Learn what modules are, how importing works under the hood, master five core built-in modules (math, random, datetime, os, sys), create custom user-defined modules, structure professional packages with __init__.py, install third-party libraries using pip, and isolate dependencies with Virtual Environments (venv).

Curriculum Level 1st Year BCA / B.Tech / Diploma
Unit Code PY-109 (Modular Architecture)
Content Balance 50% Theory • 30% Code • 20% Flowcharts
Target Standard University Exam & Production Ready
📐 Formula Verified: 50% Comprehensive Theory 30% Verified Code 20% Visual Flowcharts
1

What are Modules? Theory, Need, and Advantages

📌 What is a Module? (Formal Definition)

In Python, a module is a single file containing Python definitions and executable statements with a .py extension. The file name is the module name with the suffix .py appended (for example, a file named geometry.py is a module named geometry). A module can define functions, classes, and variables, and can also include runnable initialization code.

📐 FLOWCHART 1: MONOLITHIC SCRIPT VS. MODULAR SYSTEM ARCHITECTURE Architectural Evolution
🔴 The Monolithic Script (Anti-Pattern)
Single massive 4,000-line main.py file containing UI, math formulas, database queries, and email logic. Impossible to debug, test, or share across team members.
➔ Modularize ➔
🟢 The Modular Architecture (Industry Standard)
Cleanly segregated files: calculator.py (Math), auth.py (Security), db.py (Storage). Main file simply imports what it needs!
🧰 The Master Mechanic's Toolbox Analogy: Imagine a mechanic who welds all of their wrenches, screwdrivers, drill bits, and hammers together into one giant 50-kilogram steel lump. Using it would be impossible!
Instead, an organized mechanic keeps screwdrivers in one drawer, wrenches in another, and drill bits in a labeled kit. In Python, each organized drawer is a Module, and the entire multi-drawer cabinet is a Package.

Why Do We Need Modules? (The 4 Pillars of Modularity)

  1. Code Reusability: Once you write and test a complex algorithm (e.g. GST tax calculation) inside tax_engine.py, you can import and use it in 50 different projects without ever copying and pasting code.
  2. Namespace Isolation: In a large company with 20 developers, two programmers might both want to create a function named login(). If everything was in one file, the names would clash. Modules create separate namespaces: customer.login() and admin.login() coexist without conflicts!
  3. Maintainability & Easier Debugging: If banking rules change, you only update banking.py. The other 99 files in the software continue working untouched.
  4. Team Collaboration: Multiple software engineers can build different modules simultaneously without causing git merge conflicts.
Concept What It Represents File System Form Example
Script A Python file designed to be executed directly from top to bottom by a user. Single .py file python run_backup.py
Module A Python file intended to be imported into other files for reuse. Single .py file import math
Package A directory collection of multiple modules with an __init__.py file. Folder containing .py files import urllib.request
Library A large collection of related packages solving an entire domain problem. Bundle of packages numpy, pandas, django
2

Importing Modules: Syntax Forms, Resolution Pipeline & `__name__`

📌 What Happens Under the Hood During an Import?

When Python encounters an import my_module statement, CPython performs three sequential actions:

  1. Searches for the file: Python looks for my_module.py in the folders listed in sys.path.
  2. Compiles to Bytecode: If needed, CPython compiles the source code into bytecode and caches it in a __pycache__/ directory as a .pyc file for high-speed subsequent imports.
  3. Executes and Binds Namespace: CPython executes the module statements from top to bottom, creates a module object in memory, and binds that module object to the identifier name in your current local namespace.
📐 FLOWCHART 2: PYTHON'S MODULE SEARCH RESOLUTION PIPELINE (sys.path) Search Order Priority
1. sys.modules Cache
Checks in-memory cache dictionary. If module was already imported earlier, returns cached reference instantly!
➔ Not in Cache ➔
2. Built-in C Modules
Checks core CPython built-in modules compiled directly into interpreter binary (e.g. sys, time).
▼ Not Built-in: Check Directories in sys.path ▼
3. Current Directory (CWD)
Checks the folder where the currently running script is located.
➔ Not Found ➔
4. PYTHONPATH & Standard Lib
Checks OS environment paths and the official Python Standard Library folder.
➔ Not Found ➔
5. site-packages
Checks third-party libraries installed via pip.
▼ Exhausted All Folders in sys.path ▼
💥 ModuleNotFoundError: No module named 'xyz'
Python raises an exception if the file cannot be located anywhere in the search chain.

The 4 Syntactical Forms of Importing

Syntax Form How to Access Contents Advantages / Warnings
import math math.sqrt(25) Clean & Safe: Prevents any naming clashes; keeps module origin crystal clear.
import math as m m.sqrt(25) Aliasing: Shortens long module names (e.g. import numpy as np).
from math import sqrt, pi sqrt(25), pi Direct Import: No need to type module prefix. Imports only required functions.
from math import * sqrt(25), sin(0) ⚠️ Anti-Pattern (Wildcard): Pollutes current namespace; can silently overwrite your own variables. Avoid!
🐍 01_import_variants.py
# Form 1: Standard import
import math
print("Standard import:", math.factorial(5))

# Form 2: Aliased import
import math as m
print("Aliased import :", m.sqrt(64))

# Form 3: Direct selective import
from math import pi, ceil, floor
print(f"Direct import  : PI={pi:.4f}, Ceil={ceil(4.2)}, Floor={floor(4.8)}")
Terminal Output
Standard import: 120 Aliased import : 8.0 Direct import : PI=3.1416, Ceil=5, Floor=4

The if __name__ == '__main__': Construct (A Universal Exam Question!)

Every Python module has a built-in string attribute called __name__:

By placing code inside if __name__ == '__main__':, you ensure that test runs or demo statements only execute when the file is run directly, and are silently ignored when the file is imported elsewhere!

3

Core Built-in Modules: math, random, datetime, os, and sys

Python is celebrated for its "Batteries Included" philosophy: when you install Python, you automatically receive a vast library of thoroughly tested, optimized built-in modules.

3.1 The math Module: Precision Mathematical Functions

The math module provides access to underlying C-library mathematical functions. Note that all math functions operate on floating-point numbers (for complex numbers, Python provides the separate cmath module).

🐍 02_math_module.py
import math

# Constants
print("--- Constants ---")
print("Value of Pi (π):", math.pi)
print("Value of Euler's (e):", math.e)

# Rounding & Arithmetic
print("\n--- Arithmetic Functions ---")
print("Square Root of 144 :", math.sqrt(144))
print("Ceiling of 7.15    :", math.ceil(7.15))   # Rounds UP -> 8
print("Floor of 7.85      :", math.floor(7.85))  # Rounds DOWN -> 7
print("Power 2^5           :", math.pow(2, 5))
print("GCD of (48, 64)     :", math.gcd(48, 64))
Terminal Output
--- Constants --- Value of Pi (π): 3.141592653589793 Value of Euler's (e): 2.718281828459045 --- Arithmetic Functions --- Square Root of 144 : 12.0 Ceiling of 7.15 : 8 Floor of 7.85 : 7 Power 2^5 : 32.0 GCD of (48, 64) : 16

3.2 The random Module: Pseudo-Random Number Generation

The random module implements pseudo-random number generators (PRNG) using the proven Mersenne Twister algorithm. It is ideal for simulations, dice rolling, games, and statistical sampling.

🐍 03_random_module.py
import random

# 1. Random float between 0.0 and 1.0
print("random.random() :", round(random.random(), 4))

# 2. Random integer between [min, max] INCLUSIVE
dice_roll = random.randint(1, 6)
print("Rolling 6-sided dice:", dice_roll)

# 3. Random choice from a collection
fruits = ["Apple", "Banana", "Cherry", "Mango", "Orange"]
chosen_fruit = random.choice(fruits)
print("Randomly selected fruit:", chosen_fruit)

# 4. In-place shuffling of a list
cards = ["Ace", "King", "Queen", "Jack", "10"]
random.shuffle(cards)
print("Shuffled deck cards   :", cards)

# 5. Non-repeating sample (lottery selection)
lucky_draw = random.sample(range(1001, 1050), 3)
print("3 Lottery Winners    :", lucky_draw)
Terminal Output
random.random() : 0.6372 Rolling 6-sided dice: 5 Randomly selected fruit: Mango Shuffled deck cards : ['10', 'King', 'Ace', 'Jack', 'Queen'] 3 Lottery Winners : [1042, 1018, 1033]

3.3 The datetime Module: Dates, Clocks, and Date Arithmetic

The datetime module supplies classes for manipulating dates and times in both simple and complex ways. The two most common operations are date arithmetic using timedelta and formatting dates with strftime().

🐍 04_datetime_module.py
import datetime

# Current exact date and time
now = datetime.datetime.now()
print("Current Timestamp:", now)

# Formatting with strftime (String Format Time)
formatted_date = now.strftime("%A, %d %B %Y | %I:%M %p")
print("Formatted Banner :", formatted_date)

# Date Arithmetic using timedelta
today = datetime.date.today()
exam_date = today + datetime.timedelta(days=45)
print(f"Today: {today} | University Exams in 45 days: {exam_date}")
Terminal Output
Current Timestamp: 2026-10-15 15:45:10.124802 Formatted Banner : Thursday, 15 October 2026 | 03:45 PM Today: 2026-10-15 | University Exams in 45 days: 2026-11-29

3.4 The os Module: Operating System & File System Interactions

The os module provides a portable way of using operating system dependent functionality. It allows Python programs to create directories, read file paths, inspect directory contents, and check file existence across Windows, Linux, and macOS without modifying code.

🐍 05_os_module.py
import os

# 1. Current Working Directory
current_dir = os.getcwd()
print("Current Directory:", current_dir)

# 2. Constructing cross-platform file paths (uses \ on Windows, / on Linux)
file_path = os.path.join(current_dir, "student_database.csv")
print("Constructed Path :", file_path)

# 3. Checking if file exists
exists = os.path.exists(file_path)
print(f"Does file exist? : {exists}")

# 4. Listing directory contents (first 3 items)
dir_items = os.listdir(current_dir)
print(f"Folder contains {len(dir_items)} items. First 3: {dir_items[:3]}")
Terminal Output
Current Directory: C:\Users\shiva\Desktop\Shivan\Company\course-materials\python Constructed Path : C:\Users\shiva\Desktop\Shivan\Company\course-materials\python\student_database.csv Does file exist? : False Folder contains 16 items. First 3: ['index.html', 'unit-1-introduction-to-python.html', 'unit-2-basics.html']

3.5 The sys Module: Python Interpreter System Parameters

The sys module provides access to variables and functions maintained directly by the Python interpreter. It is essential for command-line arguments (sys.argv), inspecting search paths (sys.path), and halting program execution (sys.exit()).

🐍 06_sys_module.py
import sys

# 1. Python Interpreter Version
print("Python Version:", sys.version.split()[0])
print("Running on OS :", sys.platform)

# 2. Command-Line Arguments passed to script
print("\nCommand-line arguments (sys.argv):", sys.argv)

# 3. Module Search Paths (sys.path)
print(f"\nsys.path contains {len(sys.path)} search directories.")
print("Primary search folder (CWD):", sys.path[0])
Terminal Output
Python Version: 3.12.2 Running on OS : win32 Command-line arguments (sys.argv): ['06_sys_module.py'] sys.path contains 6 search directories. Primary search folder (CWD): C:\Users\shiva\Desktop\Shivan\Company\course-materials\python
4

Creating User-Defined Modules: Step-by-Step Architecture

📌 What is a User-Defined Module?

Creating your own module in Python does not require special commands or compilers. Any Python file you create is automatically a module! To use it, simply save functions and constants in a .py file and import it into another script within the same directory.

Step 1: Create the Module File (`grade_calculator.py`)

📄 grade_calculator.py (The Module)
"""
Module Name: grade_calculator.py
Description: User-defined module providing grading utilities.
"""

PASSING_PERCENTAGE = 40.0  # Module Constant

def calculate_percentage(obtained, total):
    """Computes percentage rounded to 2 decimal places."""
    if total <= 0:
        return 0.0
    return round((obtained / total) * 100, 2)

def assign_letter_grade(percentage):
    """Assigns university letter grade based on percentage."""
    if percentage >= 85: return "A+"
    elif percentage >= 70: return "A"
    elif percentage >= 50: return "B"
    elif percentage >= PASSING_PERCENTAGE: return "C"
    else: return "F (Fail)"

# Self-test block: Only runs when executing this file directly!
if __name__ == "__main__":
    print("[SELF-TEST] Testing module logic...")
    test_pct = calculate_percentage(420, 500)
    print(f"[SELF-TEST] 420/500 = {test_pct}% -> Grade: {assign_letter_grade(test_pct)}")

Step 2: Import & Use in Main Application (`app.py`)

🐍 app.py (The Consumer Script)
# Importing our custom user-defined module!
import grade_calculator as gc

student_name = "Priya Sharma"
obtained_marks = 445
maximum_marks = 500

# Calling functions defined inside grade_calculator module
pct = gc.calculate_percentage(obtained_marks, maximum_marks)
grade = gc.assign_letter_grade(pct)

print(f"Student Name : {student_name}")
print(f"Marks Scored : {obtained_marks}/{maximum_marks}")
print(f"Percentage   : {pct}%")
print(f"Final Grade  : {grade}")
print(f"Pass Cutoff  : {gc.PASSING_PERCENTAGE}%")
Terminal Output
Student Name : Priya Sharma Marks Scored : 445/500 Percentage : 89.0% Final Grade : A+ Pass Cutoff : 40.0%
5

Packages: Organizing Modules into Hierarchical Namespaces

📌 What is a Python Package?

A package is a directory on the file system that contains multiple Python modules and a special file named __init__.py. Packages allow multi-level hierarchical structuring using dot notation (e.g. import college.admissions.forms).

📐 FLOWCHART 3: DIRECTORY ANATOMY OF A PYTHON PACKAGE Directory Structure
📁 university_portal/              # Top-level Root Package
│── __init__.py                    # Marks directory as a Python package
│── admissions.py                  # Submodule for student enrollment
│── examinations.py                # Submodule for marks and grading
└── 📁 finance/                    # Subpackage
    │── __init__.py                # Marks finance as a subpackage
    └── fee_billing.py             # Submodule for fee receipts

The Crucial Role of `__init__.py`

🐍 importing_from_packages.py
# Style 1: Import full module path
import university_portal.examinations as exams
exams.publish_results("BCA Sem 1")

# Style 2: Import specific submodule function directly
from university_portal.finance.fee_billing import generate_receipt
receipt_id = generate_receipt(student_id=1082, amount=25000)
print("Generated Receipt ID:", receipt_id)
6

Installing Packages Using pip and The PyPI Ecosystem

📌 What is pip & PyPI?

pip stands for "Pip Installs Packages". It is the official package management system for Python, pre-installed with modern Python distributions. PyPI (Python Package Index) is the official central cloud repository hosting over 500,000 free, open-source Python packages created by software developers worldwide (such as requests for internet APIs, pandas for data analysis, and flask for web development).

📐 FLOWCHART 4: HOW pip INSTALLS PACKAGES FROM PyPI CLOUD Package Distribution Flow
1. Developer Terminal
You type: pip install requests in PowerShell or Command Prompt.
➔ Query ➔
2. PyPI Cloud (pypi.org)
PyPI repository resolves package versions and identifies any secondary dependencies.
➔ Download ➔
3. Local site-packages
Files downloaded, unpacked, and placed into your Python installation's site-packages.

Essential pip Commands for Every Python Student

Command What It Does Real Example
pip install <pkg> Downloads and installs the latest version of a package. pip install requests
pip install <pkg>==<ver> Installs an exact specific version of a package. pip install flask==2.3.0
pip list Displays all packages currently installed in the environment. pip list
pip show <pkg> Shows detailed metadata: author, version, license, location. pip show requests
pip uninstall <pkg> Cleanly removes an installed package. pip uninstall requests
pip freeze > requirements.txt Exports an exact list of all project dependencies to a text file. pip freeze > requirements.txt
pip install -r requirements.txt Installs all packages listed in a requirements file in one command! pip install -r requirements.txt
💻 Command Prompt / PowerShell Session pip CLI
C:\Users\shivan> pip install requests
Collecting requests
Downloading requests-2.31.0-py3-none-any.whl (62 kB)
Collecting urllib3<3,>=1.21.1
Installing collected packages: urllib3, requests
Successfully installed requests-2.31.0 urllib3-2.2.1
7

Virtual Environments (venv): Why Dependency Isolation Matters

📌 What is a Virtual Environment?

A Virtual Environment is an isolated, self-contained directory tree that contains its own Python interpreter and independent set of libraries. Packages installed inside a virtual environment do not interfere with other virtual environments or with the global system Python installation.

📐 FLOWCHART 5: THE GLOBAL DEPENDENCY CONFLICT VS. ISOLATED VIRTUAL ENVIRONMENTS Isolation Mechanics
❌ Without venv (Global Nightmare)
Project A requires Django 3.2. Project B requires Django 5.0. Upgrading Django for Project B breaks Project A completely!
➔ Solved By ➔
✅ With venv (Isolated Sandboxes)
env_proj_a/ contains Django 3.2.
env_proj_b/ contains Django 5.0.
Both run smoothly without conflict!

Step-by-Step Practical Guide to Using `venv`

  1. Step 1: Create a Virtual Environment
    Navigate to your project directory and run:
    python -m venv myenv
    (This creates a folder named myenv/ containing a private Python copy).
  2. Step 2: Activate the Virtual Environment
    On Windows (PowerShell): .\myenv\Scripts\Activate.ps1
    On Windows (Command Prompt): myenv\Scripts\activate.bat
    On macOS / Linux: source myenv/bin/activate
    (Your terminal prompt will change to show (myenv) at the beginning).
  3. Step 3: Install Packages Safely Inside Sandbox
    pip install requests flask
  4. Step 4: Deactivate When Finished
    Type: deactivate
8

Unit 9 Practical Capstone: Multi-Module Utility System

This capstone demonstrates how clean modular code works in production: using math, random, datetime, and sys together inside an organized business logic module.

🐍 company_billing_system.py
import math
import random
import datetime
import sys

def generate_order_id():
    """Generates a unique random order ID with current timestamp."""
    timestamp = datetime.datetime.now().strftime("%Y%m%d")
    random_suffix = random.randint(1000, 9999)
    return f"ORD-{timestamp}-{random_suffix}"

def calculate_cart_total(item_prices, discount_rate=0.10, tax_rate=0.18):
    """Calculates gross total, applies discount, and adds GST using math functions."""
    gross_amount = sum(item_prices)
    discount_amount = gross_amount * discount_rate
    discounted_subtotal = gross_amount - discount_amount
    tax_amount = discounted_subtotal * tax_rate
    
    # Using math.ceil to round up invoice cents
    final_payable = math.ceil(discounted_subtotal + tax_amount)
    
    return {
        "order_id": generate_order_id(),
        "gross": gross_amount,
        "discount": round(discount_amount, 2),
        "tax": round(tax_amount, 2),
        "total": final_payable,
        "created_at": datetime.datetime.now().strftime("%d-%b-%Y %I:%M %p")
    }

# Execution demonstration
cart_items = [499.0, 1299.0, 249.50, 850.0]
invoice = calculate_cart_total(cart_items)

print("============================================")
print(f"  INVOICE: {invoice['order_id']}")
print("============================================")
print(f"  Date & Time    : {invoice['created_at']}")
print(f"  Items Count    : {len(cart_items)}")
print(f"  Gross Subtotal : ₹{invoice['gross']:.2f}")
print(f"  Discount (10%) : -₹{invoice['discount']:.2f}")
print(f"  GST Tax (18%)  : +₹{invoice['tax']:.2f}")
print("--------------------------------------------")
print(f"  FINAL PAYABLE  : ₹{invoice['total']}")
print("============================================")
Terminal Output
============================================ INVOICE: ORD-20261015-8421 ============================================ Date & Time : 15-Oct-2026 03:52 PM Items Count : 4 Gross Subtotal : ₹2897.50 Discount (10%) : -₹289.75 GST Tax (18%) : +₹469.40 -------------------------------------------- FINAL PAYABLE : ₹3078 ============================================
9

University Exam & Viva Preparation Guide (Frequently Asked Questions)

Q1. What is a Module in Python? What are its primary advantages?
A module is a single file with a .py extension containing Python definitions (functions, classes, variables) and executable statements. The four major advantages are: (1) Code Reusability, (2) Namespace Isolation, (3) Maintainability, and (4) Team Collaboration.
Q2. What is the difference between a Module and a Package?
A module is a single Python code file (e.g. math.py).
A package is a file system directory containing multiple modules and a special __init__.py file, providing a hierarchical multi-level namespace (e.g. urllib.request).
Q3. What is the significance of the `if __name__ == '__main__':` construct?
When a Python file is run directly, CPython sets its __name__ variable to "__main__". When imported into another file, __name__ is set to the module's file name. This construct allows developers to include test blocks or scripts that execute only when the file is run directly, without running during imports.
Q4. What is `sys.path` and how does Python resolve imported modules?
sys.path is a list of directory strings where Python searches for modules. Python searches in this order: (1) In-memory sys.modules cache, (2) Built-in C modules, (3) Current working directory, (4) PYTHONPATH and Standard Library, (5) site-packages. If not found, it raises ModuleNotFoundError.
Q5. Why should every Python project use a Virtual Environment (`venv`)?
Virtual environments create isolated sandboxes with their own Python interpreter and library paths. They prevent dependency version conflicts (e.g. Project 1 needing Library v1.0 and Project 2 needing Library v2.0) and prevent polluting the global operating system Python installation.
Q6. What does `pip freeze > requirements.txt` do?
It inspects the current environment and writes the exact names and version numbers of all installed packages to a text file. Another developer can run pip install -r requirements.txt to recreate the exact identical development environment.