Creating Modules
Learning Objectives
- By the end of this lesson, you will be able to:
- - Create your own Python modules
- - Understand module structure and organization
- - Use `__name__` and `__main__` for module execution
- - Write module documentation
- - Organize code into reusable modules
- - Understand module naming conventions
- - Create modules with functions and classes
- - Make modules executable as scripts
- - Apply module best practices
Lesson 11.2: Creating Modules
Learning Objectives
By the end of this lesson, you will be able to:
- Create your own Python modules
- Understand module structure and organization
- Use
__name__and__main__for module execution - Write module documentation
- Organize code into reusable modules
- Understand module naming conventions
- Create modules with functions and classes
- Make modules executable as scripts
- Apply module best practices
Introduction to Creating Modules
Creating your own modules allows you to organize code, reuse functionality, and build maintainable applications.
What Makes a Module?
- Python file: Any
.pyfile can be a module - Functions and classes: Define reusable code
- Variables: Module-level constants
- Documentation: Docstrings and comments
Benefits of Creating Modules
- Code organization: Group related functionality
- Reusability: Use in multiple programs
- Maintainability: Easier to maintain and update
- Testing: Test modules independently
Module Structure
Basic Module Structure
"""
Module docstring - describes what the module does.
"""
# Imports
import os
import math
# Constants
PI = 3.14159
VERSION = "1.0.0"
# Functions
def greet(name):
"""Greet a person."""
return f"Hello, {name}!"
# Classes
class Calculator:
"""A simple calculator class."""
def add(self, a, b):
return a + b
# Module-level code (runs on import)
print("Module loaded")
Example: Simple Module
# mymodule.py
"""A simple example module."""
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract b from a."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide a by b."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Using Your Module
# main.py
import mymodule
result = mymodule.add(5, 3)
print(result) # Output: 8
__name__ and __main__
The __name__ variable indicates how a module is being used.
Understanding __name__
- When imported:
__name__is the module name - When run directly:
__name__is"__main__"
Basic __name__ Usage
# mymodule.py
def function():
print("Function called")
print(f"Module name: {__name__}")
# When imported: Module name: mymodule
# When run directly: Module name: __main__
Using if __name__ == "__main__":
This pattern allows code to run when the module is executed directly, but not when imported.
# mymodule.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
# Code that runs when module is executed directly
if __name__ == "__main__":
print("Running module directly")
print(add(5, 3))
print(subtract(10, 4))
Example: Module with Main Block
# calculator.py
"""Calculator module with basic operations."""
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract two numbers."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide two numbers."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
# Main block - runs when script is executed directly
if __name__ == "__main__":
print("Calculator Module")
print("=" * 30)
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
print(f"6 * 7 = {multiply(6, 7)}")
print(f"15 / 3 = {divide(15, 3)}")
Running Module as Script
# Run module directly
python calculator.py
# Import module (main block doesn't run)
python -c "import calculator; print(calculator.add(5, 3))"
Module Documentation
Module Docstring
"""
This is a module docstring.
It describes what the module does, its purpose, and how to use it.
It can span multiple lines and is accessible via __doc__.
"""
def function():
"""Function docstring."""
pass
Complete Module with Documentation
"""
Math Utilities Module
This module provides various mathematical utility functions
including arithmetic operations, number validation, and calculations.
Author: Your Name
Date: 2024-03-15
Version: 1.0.0
"""
def add(a, b):
"""
Add two numbers.
Args:
a: First number
b: Second number
Returns:
Sum of a and b
Example:
>>> add(5, 3)
8
"""
return a + b
def is_even(number):
"""
Check if a number is even.
Args:
number: Number to check
Returns:
True if number is even, False otherwise
Example:
>>> is_even(4)
True
>>> is_even(5)
False
"""
return number % 2 == 0
Accessing Module Documentation
import mymodule
# Access module docstring
print(mymodule.__doc__)
# Access function docstring
print(mymodule.add.__doc__)
# Or use help()
help(mymodule)
help(mymodule.add)
Module Organization
Organizing Functions
# math_utils.py
"""Mathematical utility functions."""
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract two numbers."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide two numbers."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Organizing Classes
# shapes.py
"""Shape classes for geometric calculations."""
import math
class Circle:
"""Represents a circle."""
def __init__(self, radius):
self.radius = radius
def area(self):
"""Calculate circle area."""
return math.pi * self.radius ** 2
def circumference(self):
"""Calculate circle circumference."""
return 2 * math.pi * self.radius
class Rectangle:
"""Represents a rectangle."""
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
"""Calculate rectangle area."""
return self.width * self.height
def perimeter(self):
"""Calculate rectangle perimeter."""
return 2 * (self.width + self.height)
Module with Constants
# constants.py
"""Application constants."""
# Application info
APP_NAME = "My Application"
VERSION = "1.0.0"
AUTHOR = "Your Name"
# Configuration
MAX_RETRIES = 3
TIMEOUT = 30
DEBUG = False
# Mathematical constants
PI = 3.141592653589793
E = 2.718281828459045
Practical Examples
Example 1: String Utilities Module
# string_utils.py
"""String manipulation utilities."""
def reverse_string(text):
"""Reverse a string."""
return text[::-1]
def capitalize_words(text):
"""Capitalize first letter of each word."""
return text.title()
def count_words(text):
"""Count words in a string."""
return len(text.split())
def remove_whitespace(text):
"""Remove all whitespace from string."""
return text.replace(" ", "")
if __name__ == "__main__":
test_string = "hello world python"
print(f"Original: {test_string}")
print(f"Reversed: {reverse_string(test_string)}")
print(f"Capitalized: {capitalize_words(test_string)}")
print(f"Word count: {count_words(test_string)}")
Example 2: File Utilities Module
# file_utils.py
"""File operation utilities."""
import os
from pathlib import Path
def file_exists(filename):
"""Check if file exists."""
return os.path.exists(filename)
def get_file_size(filename):
"""Get file size in bytes."""
if file_exists(filename):
return os.path.getsize(filename)
return None
def read_file_lines(filename):
"""Read file and return lines as list."""
if not file_exists(filename):
raise FileNotFoundError(f"File '{filename}' not found")
with open(filename, 'r') as file:
return file.readlines()
def write_file(filename, content):
"""Write content to file."""
with open(filename, 'w') as file:
file.write(content)
if __name__ == "__main__":
# Test the module
test_file = "test.txt"
write_file(test_file, "Hello, World!\nPython is great!")
print(f"File exists: {file_exists(test_file)}")
print(f"File size: {get_file_size(test_file)} bytes")
lines = read_file_lines(test_file)
print(f"Lines: {lines}")
Example 3: Data Validation Module
# validators.py
"""Data validation utilities."""
def validate_email(email):
"""Validate email address format."""
if not isinstance(email, str):
return False
return "@" in email and "." in email.split("@")[1]
def validate_age(age):
"""Validate age (must be positive integer)."""
if not isinstance(age, int):
return False
return 0 <= age <= 150
def validate_phone(phone):
"""Validate phone number format."""
if not isinstance(phone, str):
return False
# Simple validation: 10 digits
digits = ''.join(filter(str.isdigit, phone))
return len(digits) == 10
if __name__ == "__main__":
# Test validators
print(validate_email("user@example.com")) # True
print(validate_email("invalid")) # False
print(validate_age(30)) # True
print(validate_age(-5)) # False
print(validate_phone("123-456-7890")) # True
Module Best Practices
1. Use Descriptive Names
# Good: Descriptive name
import math_utils
import file_helpers
import data_validators
# Avoid: Generic names
import utils
import helpers
import stuff
2. Write Documentation
"""
Module docstring explaining purpose and usage.
"""
def function():
"""Function docstring with parameters and return value."""
pass
3. Organize Code Logically
# 1. Module docstring
# 2. Imports
# 3. Constants
# 4. Functions
# 5. Classes
# 6. if __name__ == "__main__":
4. Use if __name__ == "__main__":
def main_functionality():
pass
if __name__ == "__main__":
# Code to run when executed directly
main_functionality()
5. Avoid Module-Level Code (when imported)
# Avoid: Code that runs on import
print("Module loaded") # Runs every time module is imported
# Better: Use if __name__ == "__main__":
if __name__ == "__main__":
print("Module loaded") # Only runs when executed directly
Common Mistakes and Pitfalls
1. Module-Level Side Effects
# WRONG: Side effects on import
print("Module imported") # Runs every time!
# BETTER: Use if __name__ == "__main__":
if __name__ == "__main__":
print("Module executed directly")
2. Poor Module Names
# WRONG: Generic or confusing names
import utils
import helper
import stuff
# BETTER: Descriptive names
import math_utils
import file_helpers
import data_processors
3. Missing Documentation
# WRONG: No documentation
def function(x, y):
return x + y
# BETTER: Include docstrings
def function(x, y):
"""Add two numbers together."""
return x + y
4. Circular Imports
# WRONG: Circular import
# module_a.py
import module_b
# module_b.py
import module_a # Circular!
# BETTER: Reorganize to avoid circular dependencies
Practice Exercise
Exercise: Creating Modules
Objective: Create Python modules demonstrating module structure and best practices.
Instructions:
-
Create multiple module files that demonstrate:
- Module structure
- Functions and classes
- Documentation
__name__and__main__- Module organization
-
Create a main file that imports and uses your modules
-
Your modules should include:
- Module docstrings
- Function docstrings
- Constants
- Functions
- Classes
- Main blocks
Example Solution:
"""
Module Creation Practice
This demonstrates creating and using Python modules.
"""
# This would be in separate files, but shown together for practice
# ============================================================
# File: math_utils.py
# ============================================================
"""
Mathematical Utilities Module
Provides basic mathematical operations and utilities.
"""
def add(a, b):
"""Add two numbers."""
return a + b
def subtract(a, b):
"""Subtract b from a."""
return a - b
def multiply(a, b):
"""Multiply two numbers."""
return a * b
def divide(a, b):
"""Divide a by b."""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def is_even(number):
"""Check if number is even."""
return number % 2 == 0
def is_prime(number):
"""Check if number is prime."""
if number < 2:
return False
for i in range(2, int(number ** 0.5) + 1):
if number % i == 0:
return False
return True
if __name__ == "__main__":
print("Math Utils Module")
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
print(f"6 * 7 = {multiply(6, 7)}")
print(f"15 / 3 = {divide(15, 3)}")
print(f"Is 4 even? {is_even(4)}")
print(f"Is 7 prime? {is_prime(7)}")
# ============================================================
# File: string_utils.py
# ============================================================
"""
String Utilities Module
Provides string manipulation functions.
"""
def reverse_string(text):
"""Reverse a string."""
return text[::-1]
def capitalize_words(text):
"""Capitalize first letter of each word."""
return text.title()
def count_words(text):
"""Count words in a string."""
return len(text.split())
def remove_whitespace(text):
"""Remove all whitespace from string."""
return text.replace(" ", "")
def is_palindrome(text):
"""Check if string is a palindrome."""
cleaned = text.lower().replace(" ", "")
return cleaned == cleaned[::-1]
if __name__ == "__main__":
test_string = "hello world"
print(f"Original: {test_string}")
print(f"Reversed: {reverse_string(test_string)}")
print(f"Capitalized: {capitalize_words(test_string)}")
print(f"Word count: {count_words(test_string)}")
print(f"Is 'racecar' palindrome? {is_palindrome('racecar')}")
# ============================================================
# File: constants.py
# ============================================================
"""
Constants Module
Application-wide constants.
"""
APP_NAME = "My Application"
VERSION = "1.0.0"
AUTHOR = "Python Learner"
# Mathematical constants
PI = 3.141592653589793
E = 2.718281828459045
# Configuration
MAX_RETRIES = 3
TIMEOUT = 30
# Status codes
STATUS_OK = 200
STATUS_ERROR = 500
STATUS_NOT_FOUND = 404
if __name__ == "__main__":
print(f"Application: {APP_NAME}")
print(f"Version: {VERSION}")
print(f"Author: {AUTHOR}")
print(f"PI: {PI}")
print(f"E: {E}")
# ============================================================
# File: shapes.py
# ============================================================
"""
Shapes Module
Geometric shape classes and calculations.
"""
import math
class Circle:
"""Represents a circle."""
def __init__(self, radius):
self.radius = radius
def area(self):
"""Calculate circle area."""
return math.pi * self.radius ** 2
def circumference(self):
"""Calculate circle circumference."""
return 2 * math.pi * self.radius
class Rectangle:
"""Represents a rectangle."""
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
"""Calculate rectangle area."""
return self.width * self.height
def perimeter(self):
"""Calculate rectangle perimeter."""
return 2 * (self.width + self.height)
if __name__ == "__main__":
circle = Circle(5)
print(f"Circle (r=5): area={circle.area():.2f}, circumference={circle.circumference():.2f}")
rect = Rectangle(4, 6)
print(f"Rectangle (4x6): area={rect.area()}, perimeter={rect.perimeter()}")
# ============================================================
# File: main.py (using the modules)
# ============================================================
"""
Main script demonstrating module usage.
"""
# In a real scenario, these would be in separate files
# For this example, we'll show how they would be imported and used
print("=" * 60)
print("MODULE CREATION PRACTICE")
print("=" * 60)
print()
# Note: In practice, you would have separate .py files
# Here's how you would use them:
print("1. Using math_utils module")
print("-" * 60)
# import math_utils
# print(math_utils.add(5, 3))
# print(math_utils.is_prime(7))
print("(In practice: import math_utils)")
print()
print("2. Using string_utils module")
print("-" * 60)
# import string_utils
# print(string_utils.reverse_string("hello"))
# print(string_utils.is_palindrome("racecar"))
print("(In practice: import string_utils)")
print()
print("3. Using constants module")
print("-" * 60)
# import constants
# print(constants.APP_NAME)
# print(constants.VERSION)
print("(In practice: import constants)")
print()
print("4. Using shapes module")
print("-" * 60)
# import shapes
# circle = shapes.Circle(5)
# print(circle.area())
print("(In practice: import shapes)")
print()
print("5. Module documentation")
print("-" * 60)
# import math_utils
# print(math_utils.__doc__)
# help(math_utils)
print("(In practice: help(module_name))")
print()
print("6. __name__ variable")
print("-" * 60)
print(f"Current module __name__: {__name__}")
print("When imported, __name__ is module name")
print("When run directly, __name__ is '__main__'")
print()
print("7. Module structure example")
print("-" * 60)
print("""
# Module structure:
# 1. Module docstring
# 2. Imports
# 3. Constants
# 4. Functions
# 5. Classes
# 6. if __name__ == "__main__": block
""")
print("=" * 60)
print("PRACTICE COMPLETE!")
print("=" * 60)
print()
print("Note: In a real project, create separate .py files for each module.")
print("Then import them using: import module_name")
Expected Output:
============================================================
MODULE CREATION PRACTICE
============================================================
1. Using math_utils module
------------------------------------------------------------
(In practice: import math_utils)
[... rest of output ...]
Challenge (Optional):
- Create a complete utility module library
- Build a module with configuration management
- Create modules for specific domains (math, strings, files, etc.)
- Organize modules into a package structure
Key Takeaways
- Any
.pyfile can be a module - Module structure: docstring, imports, constants, functions, classes
__name__variable indicates how module is usedif __name__ == "__main__":runs code only when executed directly- Module docstrings describe the module's purpose
- Function docstrings document function behavior
- Use descriptive names for modules
- Organize code logically within modules
- Avoid module-level side effects when imported
- Document your modules with docstrings
- Test modules using
if __name__ == "__main__": - Module docstrings are accessible via
__doc__ - Help function shows module documentation
- Separate modules by functionality
- Follow PEP 8 style guidelines for modules
Quiz: Module Creation
Test your understanding with these questions:
-
What makes a Python file a module?
- A) Special declaration
- B) Any .py file
- C) Must have classes
- D) Must be in package
-
What is
__name__when a module is imported?- A)
"__main__" - B) Module filename
- C)
None - D)
"module"
- A)
-
What is
__name__when a module is run directly?- A) Module filename
- B)
"__main__" - C)
None - D)
"module"
-
What does
if __name__ == "__main__":do?- A) Always runs
- B) Runs only when imported
- C) Runs only when executed directly
- D) Never runs
-
Where should module docstring be placed?
- A) At end of file
- B) At top of file
- C) After imports
- D) Doesn't matter
-
What should you avoid in modules?
- A) Functions
- B) Classes
- C) Side effects on import
- D) Documentation
-
How do you access module documentation?
- A)
module.__doc__ - B)
module.doc - C)
module.help() - D)
module.info()
- A)
-
What is the recommended module structure?
- A) Random order
- B) Docstring, imports, code
- C) Code, imports, docstring
- D) Doesn't matter
-
What should module names be?
- A) Generic
- B) Descriptive
- C) Short
- D) Numbers
-
How do you make a module executable as script?
- A)
if __main__ - B)
if __name__ == "__main__": - C)
if main(): - D)
if run():
- A)
Answers:
- B) Any .py file (any Python file can be a module)
- B) Module filename (name is the module name when imported)
- B)
"__main__"(name is "main" when run directly) - C) Runs only when executed directly (main block pattern)
- B) At top of file (module docstring should be first)
- C) Side effects on import (avoid code that runs on import)
- A)
module.__doc__(access module docstring) - B) Docstring, imports, code (recommended structure)
- B) Descriptive (use descriptive module names)
- B)
if __name__ == "__main__":(standard pattern for executable modules)
Next Steps
Excellent work! You've mastered creating modules. You now understand:
- How to create modules
- Module structure and organization
- Using name and main
- Module documentation
What's Next?
- Lesson 11.3: Packages
- Learn about package structure
- Understand init.py
- Explore package organization
Additional Resources
- Modules: docs.python.org/3/tutorial/modules.html
- PEP 257 - Docstring Conventions: peps.python.org/pep-0257/
- Module Documentation: docs.python.org/3/tutorial/modules.html#more-on-modules
Lesson completed! You're ready to move on to the next lesson.
Course Navigation
- Importing Modules
- Creating Modules and Packages
- Creating Modules
- Packages
- Standard Library Overview
- Importing Modules
- Creating Modules and Packages
- Creating Modules
- Packages
- Standard Library Overview