As your programs grow larger, organizing code into modules becomes essential. Modules let you split code across multiple files, making it easier to maintain, test, and reuse. Python's import system is powerful and flexible, allowing you to use code from the standard library, third-party packages, and your own modules.
In this lesson, you'll learn how to create your own modules, use different import styles, understand Python's module search path, and organize code effectively. This knowledge is crucial for building larger applications and working with Python's ecosystem.
What You'll Learn
- Creating your own modules
- Import statements (import, from...import, import as)
- Module search path
- The name == "main" pattern
- Organizing code into modules
- Best practices for module design
What is a Module?
A module is a file containing Python code. You can import functions, classes, and variables from modules:
# math_utils.py (a module file)
def add(a, b):
"""Add two numbers."""
return a + b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
PI = 3.14159
Basic Import Statements
There are several ways to import from modules:
# Import entire module
import math_utils
result = math_utils.add(3, 4)
print(math_utils.PI)
# Import specific items
from math_utils import add, multiply
result = add(3, 4) # No module prefix needed
# Import with alias
import math_utils as mu
result = mu.add(3, 4)
# Import all (not recommended)
from math_utils import *
result = add(3, 4)
Creating Your Own Modules
Let's create a practical module:
# calculator.py
class Calculator:
"""Simple calculator class."""
def __init__(self):
self.history = []
def add(self, a, b):
result = a + b
self.history.append(f"{a} + {b} = {result}")
return result
def subtract(self, a, b):
result = a - b
self.history.append(f"{a} - {b} = {result}")
return result
def get_history(self):
return self.history
def quick_add(a, b):
"""Quick addition function."""
return a + b
# Using the module in another file
# main.py
from calculator import Calculator, quick_add
calc = Calculator()
result = calc.add(5, 3)
print(quick_add(10, 20))
The name == "main" Pattern
This pattern lets modules be both imported and run as scripts:
# utils.py
def helper_function():
return "Helper function"
def main():
"""Main function to run when script is executed directly."""
print("Running utils.py as a script")
print(helper_function())
if __name__ == "__main__":
main()
# When imported: __name__ is "utils", main() doesn't run
# When run directly: __name__ is "__main__", main() runs
This is useful for testing and providing command-line interfaces:
# math_operations.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
if __name__ == "__main__":
# Test the functions when run directly
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
Module Search Path
Python searches for modules in specific locations:
import sys
print(sys.path) # Shows where Python looks for modules
# You can add custom paths
sys.path.append("/path/to/your/modules")
The search order is:
1. Current directory
2. Directories in PYTHONPATH
3. Standard library directories
4. Site-packages (third-party packages)
Organizing Code into Modules
Here's how to structure a multi-module project:
# shapes.py
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
# utils.py
def format_area(shape):
"""Format area for display."""
return f"Area: {shape.area():.2f}"
# main.py
from shapes import Rectangle, Circle
from utils import format_area
rect = Rectangle(5, 3)
circle = Circle(4)
print(format_area(rect))
print(format_area(circle))
Import Best Practices
Follow these guidelines for clean imports:
# Good: Import standard library first
import os
import sys
from datetime import datetime
# Then third-party
import requests
import numpy as np
# Finally your own modules
from my_module import my_function
# Avoid: Wildcard imports (pollutes namespace)
# from module import * # Don't do this
# Good: Specific imports
from module import function1, function2
# Good: Use aliases for long names
import very_long_module_name as vlm
Practical Examples
Here are real-world module examples:
# config.py - Configuration module
DATABASE_URL = "localhost:5432"
API_KEY = "secret123"
DEBUG = True
def get_config():
"""Return configuration dictionary."""
return {
"database": DATABASE_URL,
"api_key": API_KEY,
"debug": DEBUG
}
# user.py - User management module
class User:
def __init__(self, username, email):
self.username = username
self.email = email
def __str__(self):
return f"User({self.username}, {self.email})"
def create_user(username, email):
"""Factory function to create users."""
return User(username, email)
# main.py - Main application
from config import get_config, DEBUG
from user import User, create_user
config = get_config()
if DEBUG:
print("Debug mode enabled")
user = create_user("alice", "alice@example.com")
print(user)
Reloading Modules
During development, you might need to reload modules:
import importlib
import my_module
# Reload the module
importlib.reload(my_module)
Try It Yourself
Practice creating and using modules:
-
Math Module: Create a
math_utils.pymodule with functions for common math operations. Import and use it in another file. -
String Utilities: Create a
string_utils.pymodule with string manipulation functions. Test it using the__name__ == "__main__"pattern. -
Data Processing: Create separate modules for data loading, processing, and saving. Import them in a main script.
-
Configuration: Create a
config.pymodule with settings and amain.pythat imports and uses those settings. -
Class Library: Create a module with multiple classes (e.g.,
shapes.pywith Rectangle, Circle, Triangle). Import specific classes in another file.
Summary
Modules are essential for organizing Python code. You can create your own modules, import from them using various styles, and structure projects effectively. The __name__ == "__main__" pattern lets modules work as both libraries and scripts. Understanding Python's module search path helps you organize and import code correctly.
As you build larger applications, modular code becomes increasingly important. Well-organized modules make code easier to maintain, test, and reuse. This foundation prepares you for working with packages and larger Python projects.
What's Next?
In the next lesson, we'll explore packages—collections of modules organized in directories. You'll learn how to create packages, use __init__.py, understand relative vs absolute imports, and work with virtual environments for managing dependencies.