Modules and Packages

Chapter 5: Modules and Packages

Modules organize code into reusable files, preventing repetition and enabling logical structure. Instead of writing all code in one massive file, you split functionality into separate modules that can be imported as needed. Python's module system, combined with its extensive standard library, lets you build sophisticated programs by combining pre-built and custom components.

For example, instead of rewriting mathematical functions, you import Python's math module to access trigonometry, logarithms, and constants instantly. Learning to work with modules and packages is essential for any Python developer—it's how you leverage existing code and organize your own projects effectively.

Importing Modules

Python's import statement loads modules, making their functions and variables available in your code. The simplest form imports an entire module:

When you import a module, you access its contents using dot notation: module.name. This keeps the module's namespace separate from your code, preventing name conflicts.

Selective Imports with from...import

Sometimes you only need specific items from a module. The from...import syntax brings those items directly into your namespace:

This approach is cleaner when you frequently use certain functions, but be careful—importing too many items can make it unclear where functions come from. Balance convenience with code clarity.

You can import everything with from math import *, but this is discouraged in production code. It pollutes your namespace and makes it hard to track where names originate.

Import Aliasing with as

Give imports shorter or clearer names using the as keyword:

import math as m
from datetime import datetime as dt

circumference = 2 * m.pi * 5
print(f"Circumference: {circumference}")

now = dt.now()
print(f"Current time: {now}")

Aliasing is particularly useful for long module names or when avoiding conflicts. Many libraries have conventional aliases: import pandas as pd, import numpy as np. Following these conventions makes your code familiar to other developers.

Python's Standard Library

Python includes a vast standard library—modules that come built-in, covering everything from math to web requests. Learning to use the standard library prevents reinventing the wheel and saves enormous development time.

Common Standard Library Modules

The math module provides mathematical functions beyond basic arithmetic:

import math

# Trigonometry
angle_rad = math.radians(45)  # Convert degrees to radians
sine = math.sin(angle_rad)
print(f"sin(45°): {sine}")

# Logarithms and powers
log_val = math.log(100, 10)  # Log base 10
print(f"log₁₀(100): {log_val}")

# Constants
print(f"π: {math.pi}")
print(f"e: {math.e}")

The random module generates random numbers for simulations, games, and sampling:

import random

# Random integer in range
dice_roll = random.randint(1, 6)
print(f"Dice roll: {dice_roll}")

# Random choice from list
colors = ["red", "blue", "green"]
chosen = random.choice(colors)
print(f"Random color: {chosen}")

# Shuffle list in place
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(f"Shuffled: {numbers}")

The datetime module handles dates and times:

from datetime import datetime, timedelta

# Current date and time
now = datetime.now()
print(f"Now: {now}")

# Date arithmetic
tomorrow = now + timedelta(days=1)
print(f"Tomorrow: {tomorrow}")

# Format dates
formatted = now.strftime("%Y-%m-%d %H:%M")
print(f"Formatted: {formatted}")

The json module works with JSON data, essential for web APIs and configuration:

import json

# Python dict to JSON string
data = {"name": "Alice", "age": 30, "active": True}
json_string = json.dumps(data)
print(f"JSON: {json_string}")

# JSON string to Python dict
parsed = json.loads(json_string)
print(f"Name: {parsed['name']}")

These modules barely scratch the surface. The standard library includes tools for file paths (pathlib), regular expressions (re), HTTP requests (urllib), data compression (gzip), and much more.

Creating Your Own Modules

Any Python file becomes a module. Create a file with functions or variables, then import it elsewhere in your project. For example, create calculator.py:

# calculator.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

PI = 3.14159

Import it in another file:

import calculator

result = calculator.add(5, 3)
print(result)  # Output: 8

print(calculator.PI)  # Output: 3.14159

Or use selective imports:

from calculator import add, PI

result = add(10, 5)
print(result)  # Output: 15

This modular approach keeps code organized. Related functions live together in modules, making code easier to understand and maintain.

Packages: Organizing Multiple Modules

Packages group related modules into directories. A package is simply a folder containing a special __init__.py file (which can be empty) and module files. For example, a geometry package structure:

geometry/
    __init__.py
    circle.py
    rectangle.py

Access package modules with dot notation:

from geometry import circle
from geometry.rectangle import area

# Or import specific items
from geometry.circle import area as circle_area

Packages enable hierarchical organization for large projects, keeping related functionality grouped logically.

Best Practices for Imports

Place all imports at the top of your file, organized into three groups:

  1. Standard library imports
  2. Third-party library imports
  3. Local/project imports
# Standard library
import math
from datetime import datetime

# Third-party (if using external packages)
# import requests
# import pandas as pd

# Local modules
from calculator import add

This organization makes dependencies clear at a glance.

Avoid circular imports where module A imports module B, which imports module A. This creates errors. Restructure code to break the cycle, often by extracting shared functionality to a third module.

Try It Yourself: Practice Exercises

Exercise 1: Math Operations
Import the math module. Calculate the area of a circle with radius 7, the square root of 144, and the value of e² (using math.e).

Exercise 2: Random Selection
Import random.choice. Create a list of five names and randomly select one to print.

Exercise 3: Date Calculations
Import datetime and timedelta. Print today's date, the date 30 days ago, and the date 60 days from now.

Exercise 4: JSON Conversion
Create a dictionary representing a book (title, author, year, pages). Convert it to a JSON string using json.dumps(), then parse it back using json.loads().

Exercise 5: Custom Module
Create a file temperature.py with functions celsius_to_fahrenheit(c) and fahrenheit_to_celsius(f). Import and use both functions in another file.

Exercise 6: Selective Imports
Import only sqrt and pow from the math module using from...import. Use both functions to calculate √25 and 2³.

What's Next?

You've mastered Python's module system: importing modules, using the standard library, creating your own modules, and organizing code into packages. This knowledge lets you leverage Python's ecosystem and structure larger projects effectively.

In the next chapter, we'll explore file operations—reading from and writing to files, working with paths, and handling different file formats. File I/O is essential for data persistence, configuration management, and processing external data.

Continue to Chapter 6: File Operations

📝 Test Your Knowledge: Modules and Packages

Take this quiz to reinforce what you've learned in this chapter.