Skip to content
CampusEduX

Functions, Files & OOP · Lesson 7 of 30

Modules & Packages

Organizing code into modules and packages, the different ways to import, __name__ == "__main__", and a practical tour of the Standard Library (math, random, datetime, os, sys, json, re, statistics, collections, itertools, functools).

9 min read

As programs grow, it doesn't make sense to keep everything in one giant file — and you also don't want to rewrite common functionality (like math operations or date handling) from scratch every time. Python solves this with modules and packages, plus a massive built-in Standard Library of ready-to-use tools.


01What is a Module?

What is it?

A module is simply a Python file (.py) containing code — variables, functions, classes — that can be reused in other Python files by importing it.

Why do we use it?

  • Organization — split a large program into logical, manageable files.
  • Reusability — write a function once, use it in many different programs.
  • Avoid repetition — no need to rewrite common logic (like date calculations) every time.

How does it work?

Any .py file is automatically a module. You bring its contents into another file using the import keyword.

Simple Example — Creating Your Own Module

File: `mymath.py`

python
def add(a, b): return a + b def subtract(a, b): return a - b

File: `main.py` (in the same folder)

python
import mymath print(mymath.add(5, 3)) # 8 print(mymath.subtract(5, 3)) # 2

Explanation of the Code

  • import mymath loads everything defined inside mymath.py, making it available through mymath.functionname().
  • The module name is just the filename, without the .py extension.

Common Mistakes

  • Trying to import a module that isn't in the same folder (or on Python's search path), causing ModuleNotFoundError.
  • Naming your own file the same as a well-known library (e.g., naming your file random.py), which can conflict with Python's built-in modules.

Important Points

  • Any .py file can be treated as a module.
  • The module name matches the filename (without .py).

02Different Ways to Import

Syntax Options

python
import math # import the whole module print(math.sqrt(16)) # access with module_name.function() from math import sqrt # import just one function print(sqrt(16)) # use it directly, no prefix needed from math import sqrt, pow # import multiple specific items import math as m # import with an alias (shorter name) print(m.sqrt(16)) from math import * # import EVERYTHING (generally discouraged)

Explanation

  • import math keeps things organized — you always know a function like sqrt() came from math because you write math.sqrt().
  • from math import sqrt is more convenient when you use a function frequently, but it's less clear where the function came from, especially in larger files.
  • import math as m is common for long library names (very frequently seen with libraries like pandas as pd or numpy as np).

Common Mistakes

  • Using from module import *, which can cause naming conflicts if two modules define something with the same name — it's discouraged in real projects for this reason.
  • Forgetting to install a third-party module before importing it (built-in modules like math need no installation, but others like requests do — covered in the Package Management file).

Important Points

  • import module_name is the safest, clearest default choice.
  • Aliasing (as) is a widely used convention for popular libraries.

03Packages

What is it?

A package is a folder containing multiple related modules, organized together — essentially, a "module of modules."

Folder Structure Example

myapp/
    __init__.py
    calculations.py
    formatting.py

Simple Example

File: `myapp/calculations.py`

python
def add(a, b): return a + b

File: `main.py` (outside the myapp folder)

python
from myapp import calculations print(calculations.add(5, 3)) # 8

What is __init__.py?

This special (often empty) file tells Python "this folder is a package, not just a regular folder." Without it, older versions of Python won't recognize the folder as importable (modern Python 3 can sometimes work without it via "namespace packages," but including it is still standard, clear practice).

Real-World Example

Popular libraries like numpy or django are packages — large folders full of organized modules, all accessible through a single import numpy statement.

Common Mistakes

  • Forgetting __init__.py in a package folder, leading to unexpected import behavior in some setups.
  • Confusing "module" (single file) with "package" (folder of modules) — a common interview distinction.

Important Points

  • A package is a folder; a module is a single file.
  • __init__.py marks a folder as a package.

04__name__ and __main__

What is it?

Every Python file has a built-in variable called __name__. When a file is run directly, __name__ is automatically set to "__main__". When the same file is imported into another file, __name__ is set to the module's actual name instead.

Why do we use it?

This lets you write code in a file that behaves differently depending on whether it's being run directly or just imported for its functions — extremely useful for testing a module's code without that test code running every time someone else imports it.

Simple Example

File: `greetings.py`

python
def greet(name): print(f"Hello, {name}!") if __name__ == "__main__": greet("Test User") # only runs when this file is executed directly
  • Running python greetings.py directly → prints "Hello, Test User!".
  • Running import greetings from another file → the greet() function is available, but "Hello, Test User!" does not print automatically.

Real-World Example

Almost every well-structured Python script or library uses this pattern so that importing it for its functions doesn't accidentally trigger test code or a demo run meant only for direct execution.

Common Mistakes

  • Forgetting this check entirely, causing test/demo code to run unexpectedly whenever the file is imported elsewhere.

Important Points

  • __name__ == "__main__" is a near-universal pattern in real Python projects.
  • It distinguishes "this file was run directly" from "this file was imported."

Practice

  1. 1Create a module with a function and a if __name__ == "__main__": block that tests the function. Run it directly, then import it from another file and observe the difference.

05The Python Standard Library — A Practical Tour

Python comes bundled with a huge collection of built-in modules — no installation required. Here are the most commonly used ones.

5.1 math — Mathematical Functions

python
import math print(math.sqrt(25)) # 5.0 print(math.pow(2, 3)) # 8.0 print(math.floor(4.7)) # 4 print(math.ceil(4.2)) # 5 print(math.pi) # 3.141592653589793

Real-World Use: Calculating distances, geometry, engineering formulas.

5.2 random — Random Number Generation

python
import random print(random.randint(1, 100)) # random integer between 1 and 100 print(random.choice(["A", "B", "C"])) # random item from a list print(random.random()) # random float between 0.0 and 1.0 items = [1, 2, 3, 4, 5] random.shuffle(items) # shuffles the list in place print(items)

Real-World Use: Games (like the Number Guessing Game), generating OTPs, shuffling quiz questions.

5.3 datetime — Dates and Times

python
from datetime import datetime, date now = datetime.now() print(now) # e.g. 2026-09-02 14:30:00.123456 print(now.year, now.month, now.day) birth_date = date(2000, 5, 15) today = date.today() age_days = (today - birth_date).days print(f"You are {age_days} days old")

Real-World Use: Timestamps, age calculators, scheduling systems, log files.

5.4 os — Operating System Interaction

python
import os print(os.getcwd()) # current working directory os.mkdir("new_folder") # create a folder print(os.listdir(".")) # list files in current directory print(os.path.exists("main.py")) # check if a file exists

Real-World Use: File automation, checking/creating folders, working with file paths across operating systems.

5.5 sys — System-Specific Parameters

python
import sys print(sys.version) # Python version info print(sys.argv) # command-line arguments passed to the script

Real-World Use: Reading command-line arguments, exiting a script early with sys.exit().

5.6 json — Working with JSON Data

python
import json data = {"name": "Aditi", "age": 21} json_string = json.dumps(data) # Python dict -> JSON string print(json_string) # {"name": "Aditi", "age": 21} parsed = json.loads(json_string) # JSON string -> Python dict print(parsed["name"]) # Aditi

Real-World Use: APIs almost always send and receive data in JSON format — this module is essential for web development and API work (covered in depth later).

5.7 re — Regular Expressions

python
import re text = "Call me at 9876543210" match = re.search(r"\d{10}", text) if match: print("Phone number found:", match.group())

Real-World Use: Validating emails, phone numbers, passwords (covered in full in the Regular Expressions file).

5.8 statistics — Statistical Calculations

python
import statistics marks = [85, 90, 78, 92, 88] print(statistics.mean(marks)) # average print(statistics.median(marks)) # middle value print(statistics.mode(marks)) # most common value

Real-World Use: Quick statistical summaries without needing a heavier library like NumPy for simple cases.

5.9 collections — Specialized Data Structures

python
from collections import Counter, defaultdict words = ["apple", "banana", "apple", "cherry", "banana", "apple"] print(Counter(words)) # Counter({'apple': 3, 'banana': 2, 'cherry': 1}) word_count = defaultdict(int) for word in words: word_count[word] += 1 print(dict(word_count))

Explanation: Counter instantly counts occurrences of each item. defaultdict avoids KeyError by providing a default value (here, 0) for keys that don't exist yet.

Real-World Use: Word frequency counters, grouping and tallying data.

5.10 itertools — Efficient Looping Tools

python
import itertools # All possible pairs from a list for pair in itertools.combinations([1, 2, 3], 2): print(pair) # (1, 2) # (1, 3) # (2, 3)

Real-World Use: Generating combinations/permutations, efficient looping over large or infinite sequences.

5.11 functools — Functional Programming Tools

python
from functools import reduce, lru_cache total = reduce(lambda a, b: a + b, [1, 2, 3, 4]) print(total) # 10 @lru_cache(maxsize=None) def slow_square(n): return n * n print(slow_square(5)) # cached after first call

Explanation: @lru_cache automatically remembers previous results of a function, so repeated calls with the same input skip re-computation — useful for speeding up expensive functions like recursive calculations.

Real-World Use: Speeding up repeated expensive calculations (like recursive Fibonacci), combining values with reduce.

Comparison Table — Common Standard Library Modules

ModulePurpose
mathMathematical calculations
randomRandom values, shuffling, choices
datetimeDates and times
osFile system and OS interaction
sysSystem/interpreter-level info
jsonEncoding/decoding JSON data
rePattern matching in text
statisticsQuick statistical calculations
collectionsSpecialized containers (Counter, defaultdict)
itertoolsEfficient iteration tools
functoolsFunctional programming helpers (reduce, caching)

Common Beginner Mistakes — Summary

  • Using from module import *, risking naming conflicts.
  • Naming your own files the same as standard modules (e.g., random.py), which shadows the real module.
  • Forgetting __init__.py when building a package.
  • Forgetting that import only needs to happen once per file, at the top.
  • Confusing "module" (a file) with "package" (a folder of modules).

Cheat Sheet — Modules & Packages

python
import math # standard import from math import sqrt # import specific item import math as m # import with alias from math import * # import everything (avoid in real projects) if __name__ == "__main__": # code that runs only when this file is executed directly pass
myapp/                # package (folder)
    __init__.py        # marks it as a package
    module_one.py       # a module inside the package
    module_two.py

Interview Questions

Q1. What is the difference between a module and a package?

Ans:A module is a single Python file. A package is a folder containing multiple related modules, along with an __init__.py file marking it as a package.

Q2. What does `if __name__ == "__main__":` do?

Ans:It checks whether the current file is being run directly (in which case __name__ equals "__main__") rather than imported into another file — code inside this block only runs on direct execution.

*Q3. What is the risk of using `from module import `?** Answer: It can cause naming conflicts if multiple modules define something with the same name, and it makes it unclear where a given function or variable actually came from.

Q4. Name three commonly used Python Standard Library modules and their purpose. Answer: Examples: math (mathematical functions), datetime (dates and times), os (file system and operating system interaction), json (working with JSON data), random (random values).

Q5. What does `__init__.py` do in a package?

Ans:It marks a folder as a Python package so its modules can be imported properly.


Practice Questions

Beginner

  1. 1Create your own module with two functions and import it into a separate file.
  2. 2Use the math module to calculate the square root and factorial of a number.
  3. 3Use the random module to simulate rolling a die (random number from 1 to 6).
  4. 4Use the datetime module to print today's date.
  5. 5Use the os module to list all files in the current directory.

Intermediate

  1. 1Create a package with two modules (operations.py and formatting.py) and use both in a main.py file.
  2. 2Use the json module to convert a dictionary of student data into a JSON string and back.
  3. 3Use collections.Counter to find the most common word in a list of words.
  4. 4Write a function that uses if __name__ == "__main__": to test itself only when run directly.
  5. 5Use the statistics module to calculate the mean, median, and mode of a list of exam scores.

Challenge

  1. 1Use itertools.permutations to generate all possible orderings of a 3-letter word.
  2. 2Build a simple age calculator using the datetime module that takes a birth date and prints the person's exact age in years, months, and days.
  3. 3Use functools.lru_cache to speed up a recursive Fibonacci function, and compare its execution time to the uncached version.

Mock Test

  • Modules & Packages - Quick Test

    10 questions covering modules, packages, imports, __name__ == "__main__", and the Python Standard Library.

    10 questions · 10 min · Easy
    Start Mock Test

Coding Problems