Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

Β© 2026 rakrisi Daily

Python Modules - Code Organization

Python Modules: Code Organization

Welcome to Python Modules! Think of modules as filing cabinets for your code - they help you organize functions, classes, and variables into logical, reusable components.

What is a Module?

A module is simply a Python file (.py) that contains code you can import and reuse. Every Python file you create is a module!

# greeting.py - This is a module!
def say_hello(name):
    return f"Hello, {name}!"

def say_goodbye(name):
    return f"Goodbye, {name}!"

PI = 3.14159
AUTHOR = "Your Name"

Creating Your First Module

Let’s create a simple module and use it:

# math_operations.py
def add(a, b):
    """Add two numbers together."""
    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

# Module-level variables
PI = 3.14159
E = 2.71828

Now let’s use this module:

# main.py
import math_operations

# Use functions from the module
result1 = math_operations.add(5, 3)
result2 = math_operations.multiply(4, 7)

print(f"5 + 3 = {result1}")
print(f"4 Γ— 7 = {result2}")
print(f"Ο€ β‰ˆ {math_operations.PI}")

# This will cause an error
try:
    math_operations.divide(10, 0)
except ValueError as e:
    print(f"Error: {e}")

Import Methods

Python offers several ways to import modules:

1. Import the Whole Module

import math_operations

result = math_operations.add(1, 2)

Pros: Clear where functions come from, avoids naming conflicts Cons: Longer function calls

2. Import Specific Items

from math_operations import add, multiply, PI

result = add(1, 2)  # No module prefix needed
area = multiply(PI, 5**2)  # Direct access

Pros: Shorter code, cleaner Cons: Can cause naming conflicts, unclear origins

3. Import with Alias

import math_operations as mo

result = mo.add(1, 2)

Pros: Short prefix, clear module origin Cons: Extra typing for the alias

4. Import Everything (Avoid This!)

from math_operations import *

result = add(1, 2)  # Works, but dangerous!

Cons: Pollutes namespace, unclear what’s imported, hard to debug

The if __name__ == "__main__" Pattern

A special pattern for making modules both importable and runnable:

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

def main():
    """Main function when run as script."""
    print("Simple Calculator")
    print(f"2 + 3 = {add(2, 3)}")

if __name__ == "__main__":
    main()

What happens:

  • When you run python calculator.py: __name__ is "__main__", so main() runs
  • When you import calculator: __name__ is "calculator", so main() doesn’t run

Module Search Path

When you import a module, Python searches in this order:

  1. Built-in modules (sys, os, math)
  2. Current directory (where your script runs)
  3. PYTHONPATH environment variable
  4. Installation directories (site-packages)
import sys
print(sys.path)  # Shows the search path

Module Execution

When a module is imported, Python:

  1. Finds the module file
  2. Compiles it to bytecode (.pyc files)
  3. Executes all top-level code
  4. Creates a module object
  5. Adds it to sys.modules
# demo_execution.py
print("This runs when the module is imported!")

def test_function():
    print("This only runs when called")

print("Module loaded successfully")

Module Attributes

Every module has special attributes:

import math_operations

print(f"Module name: {math_operations.__name__}")
print(f"Module file: {math_operations.__file__}")
print(f"Module doc: {math_operations.__doc__}")

# List all attributes
print(dir(math_operations))

Practical Examples

Example 1: Configuration Module

# config.py
# Application configuration
DATABASE_URL = "sqlite:///app.db"
DEBUG = True
SECRET_KEY = "your-secret-key-here"

# API settings
API_BASE_URL = "https://api.example.com"
TIMEOUT = 30

# Email settings
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
# app.py
import config

def send_email(to, subject, body):
    # Use config values
    print(f"Connecting to {config.SMTP_SERVER}:{config.SMTP_PORT}")
    print(f"Sending email to {to}")

if config.DEBUG:
    print("Running in debug mode")

send_email("user@example.com", "Hello", "Test message")

Example 2: Utility Functions

# string_utils.py
def capitalize_words(text):
    """Capitalize the first letter of each word."""
    return text.title()

def slugify(text):
    """Convert text to URL-friendly slug."""
    import re
    text = text.lower()
    text = re.sub(r'[^a-z0-9]+', '-', text)
    return text.strip('-')

def truncate(text, length=100, suffix="..."):
    """Truncate text to specified length."""
    if len(text) <= length:
        return text
    return text[:length - len(suffix)] + suffix
# blog_post.py
from string_utils import slugify, truncate

class BlogPost:
    def __init__(self, title, content):
        self.title = title
        self.slug = slugify(title)
        self.excerpt = truncate(content, 150)

    def get_url(self):
        return f"/blog/{self.slug}"

# Test the blog post
post = BlogPost("Hello World!", "This is a long blog post content...")
print(f"Title: {post.title}")
print(f"Slug: {post.slug}")
print(f"URL: {post.get_url()}")
print(f"Excerpt: {post.excerpt}")

Example 3: Data Validation

# validators.py
def is_valid_email(email):
    """Check if email is valid."""
    import re
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

def is_valid_phone(phone):
    """Check if phone number is valid (US format)."""
    import re
    pattern = r'^\+?1?[-.\s]?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$'
    return bool(re.match(pattern, phone))

def is_strong_password(password):
    """Check if password meets strength requirements."""
    if len(password) < 8:
        return False
    if not any(c.isupper() for c in password):
        return False
    if not any(c.islower() for c in password):
        return False
    if not any(c.isdigit() for c in password):
        return False
    return True
# user_registration.py
from validators import is_valid_email, is_strong_password

class User:
    def __init__(self, email, password):
        if not is_valid_email(email):
            raise ValueError("Invalid email address")
        if not is_strong_password(password):
            raise ValueError("Password is not strong enough")

        self.email = email
        self.password = password  # In real app, hash this!

    def __str__(self):
        return f"User(email='{self.email}')"

# Test user registration
try:
    user1 = User("alice@example.com", "StrongPass123!")
    print(f"Created: {user1}")

    user2 = User("invalid-email", "weak")
    print(f"Created: {user2}")
except ValueError as e:
    print(f"Registration failed: {e}")

Common Module Patterns

Constants Module

# constants.py
# Application constants
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB
DEFAULT_TIMEOUT = 30
SUPPORTED_FORMATS = ['jpg', 'png', 'gif', 'webp']

# API endpoints
API_BASE = "https://api.example.com"
ENDPOINTS = {
    'users': f"{API_BASE}/users",
    'posts': f"{API_BASE}/posts",
    'comments': f"{API_BASE}/comments"
}

Logger Module

# logger.py
import logging
import sys

def setup_logger(name, level=logging.INFO):
    """Setup a logger with console output."""
    logger = logging.getLogger(name)
    logger.setLevel(level)

    # Create console handler
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(level)

    # Create formatter
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    handler.setFormatter(formatter)

    # Add handler to logger
    logger.addHandler(handler)

    return logger

# Create default logger
default_logger = setup_logger(__name__)

Database Module

# database.py
import sqlite3
from contextlib import contextmanager

class Database:
    def __init__(self, db_path):
        self.db_path = db_path

    @contextmanager
    def get_connection(self):
        """Context manager for database connections."""
        conn = sqlite3.connect(self.db_path)
        try:
            yield conn
        finally:
            conn.close()

    def execute_query(self, query, params=None):
        """Execute a query and return results."""
        with self.get_connection() as conn:
            cursor = conn.cursor()
            if params:
                cursor.execute(query, params)
            else:
                cursor.execute(query)
            return cursor.fetchall()

# Create database instance
db = Database("app.db")

Best Practices

1. Use Descriptive Names

# Good
import user_management
from data_processing import clean_data, validate_input

# Bad
import um
from dp import cd, vi
# Good: Group related functions in modules
# string_utils.py - String operations
# file_utils.py - File operations
# math_utils.py - Math operations

# Bad: One huge utils.py with everything

3. Use __all__ for Explicit Exports

# my_module.py
__all__ = ['public_function', 'PublicClass']  # Only these are public

def public_function():
    pass

def _private_function():  # Not in __all__, considered private
    pass

class PublicClass:
    pass

class _PrivateClass:  # Not in __all__, considered private
    pass

4. Document Your Modules

"""
String Utilities Module

This module provides utility functions for string manipulation,
including formatting, validation, and transformation operations.

Author: Your Name
Version: 1.0.0
"""

def format_name(first, last):
    """Format a full name from first and last names."""
    return f"{first} {last}".title()

Practice Exercises

Exercise 1: Temperature Converter

Create a temperature.py module with functions to convert between Celsius, Fahrenheit, and Kelvin. Include:

  • celsius_to_fahrenheit()
  • fahrenheit_to_celsius()
  • celsius_to_kelvin()
  • kelvin_to_celsius()
  • Constants for freezing/boiling points

Exercise 2: File Organizer

Create a file_organizer.py module with functions to:

  • get_file_extension(filename)
  • get_file_size(filepath)
  • organize_by_extension(directory)
  • organize_by_date(directory)

Exercise 3: Text Statistics

Create a text_stats.py module with functions to:

  • count_words(text)
  • count_sentences(text)
  • average_word_length(text)
  • most_common_words(text, n=10)

Exercise 4: Currency Converter

Create a currency.py module with:

  • Exchange rate constants
  • convert_currency(amount, from_currency, to_currency)
  • format_currency(amount, currency_code)
  • Support for USD, EUR, GBP, JPY

Summary

Modules are Python’s way of organizing code:

Creating Modules:

# my_module.py
def my_function():
    return "Hello from module!"

CONSTANT = 42

Importing Modules:

import my_module                    # Full import
from my_module import my_function   # Specific import
import my_module as mm              # With alias

Key Concepts:

  • Every .py file is a module
  • Use if __name__ == "__main__" for runnable scripts
  • Python searches sys.path for modules
  • Use __all__ to control what’s exported

Best Practices:

  • Use descriptive module names
  • Group related functions together
  • Document your modules with docstrings
  • Use explicit imports over from module import *

Next: Packages - organizing modules into directories! πŸ“