W3docs

Python Modules

Learn how Python modules work: create your own, import with aliases, use from-import, explore the standard library, and understand sys.path.

A module is a file containing Python code — functions, classes, and variables — that you can reuse across multiple programs. Modules are the basic unit of code organization in Python: instead of copying logic between files, you write it once, save it as a .py file, and import it wherever you need it. This chapter covers everything from creating your first module to navigating the standard library and understanding how Python locates modules at runtime.

What Is a Python Module?

Any .py file is a module. When you write:

# greetings.py
def hello(name):
    return f"Hello, {name}!"

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

PI = 3.14159

you have created a module named greetings. The module name is the filename without the .py extension.

Modules can contain:

  • Functions — reusable blocks of logic (see Python Functions)
  • Classes — blueprints for objects (see Python Classes)
  • Variables and constants — shared data
  • Executable statements — code that runs when the module is imported or executed directly

Importing a Module

Use the import statement followed by the module name (no .py extension).

import greetings

print(greetings.hello("Alice"))    # Hello, Alice!
print(greetings.goodbye("Alice"))  # Goodbye, Alice!
print(greetings.PI)                # 3.14159

After import greetings, all names defined in greetings.py are accessible through the greetings. prefix. This dot notation prevents name collisions — your own PI variable cannot clash with greetings.PI.

Importing Specific Names with from ... import

If you only need one or two names, import them directly so you can use them without the module prefix.

from greetings import hello, PI

print(hello("Bob"))   # Hello, Bob!
print(PI)             # 3.14159

Importing Everything with *

from greetings import *

This pulls every public name (those not starting with _) into the current namespace. Avoid it in larger programs: it pollutes the namespace and makes it hard to tell where a name came from.

Import Aliases with as

Long module names become tedious to type. Use as to create a shorter alias.

import greetings as gr

print(gr.hello("Carol"))   # Hello, Carol!

You can alias individual imported names too:

from greetings import hello as hi

print(hi("Dave"))   # Hello, Dave!

Aliases are especially common with popular libraries:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

The dir() Function

dir(module) returns a sorted list of all names defined in a module — a fast way to explore what is available.

import math
print(dir(math))
# ['__doc__', '__loader__', ..., 'acos', 'acosh', 'asin', ..., 'sqrt', 'tan', 'tanh', 'tau']

Call dir() with no arguments to see the names in the current scope.

The __name__ Variable

Every module has a built-in variable called __name__. When a file is imported, __name__ is set to the module name. When the file is run directly, __name__ is set to the string "__main__".

This pattern is the standard way to write code that runs only when the file is executed as a script — not when it is imported as a library:

# greetings.py

def hello(name):
    return f"Hello, {name}!"

if __name__ == "__main__":
    # This block only runs when you execute: python greetings.py
    print(hello("World"))
import greetings   # The if-block does NOT run here

This pattern is used in almost every non-trivial Python file you will encounter.

Module Search Path (sys.path)

When you write import greetings, Python searches for the module in a list of directories stored in sys.path:

  1. The directory of the script being run (or the current directory in interactive mode)
  2. Directories listed in the PYTHONPATH environment variable
  3. The standard library directories
  4. The site-packages directory (where third-party packages installed by pip live)
import sys
print(sys.path)
# ['/path/to/script', '/usr/lib/python3.11', ..., '/usr/lib/python3/dist-packages']

You can append a path at runtime, but this is rarely needed for well-structured projects:

import sys
sys.path.append("/path/to/my/libs")

The Python Standard Library

Python ships with a large standard library — hundreds of modules covering everything from file I/O to network protocols to data compression. You do not need to install anything; just import them.

math — Mathematical Functions

import math

print(math.sqrt(16))       # 4.0
print(math.pi)             # 3.141592653589793
print(math.factorial(5))   # 120
print(math.ceil(4.2))      # 5
print(math.floor(4.8))     # 4

See Python Math for a full reference.

random — Random Numbers

import random

print(random.randint(1, 10))          # random integer between 1 and 10
print(random.choice(["a", "b", "c"])) # random element
print(random.random())                 # float in [0.0, 1.0)

numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers)   # shuffled in place

datetime — Dates and Times

import datetime

now = datetime.datetime.now()
print(now)                       # 2024-03-15 10:30:45.123456
print(now.year)                  # 2024
print(now.strftime("%B %d, %Y")) # March 15, 2024

today = datetime.date.today()
print(today)   # 2024-03-15

See Python Dates for full coverage of date arithmetic and formatting.

os and sys — Operating System and Interpreter

import os

print(os.getcwd())              # current working directory
print(os.listdir("."))          # files in the current directory
os.makedirs("new_dir", exist_ok=True)  # create a directory
print(os.path.join("folder", "file.txt"))  # 'folder/file.txt'
import sys

print(sys.version)    # Python version string
print(sys.platform)   # 'linux', 'darwin', 'win32', etc.
sys.exit(0)           # terminate the program with exit code 0

json — JSON Encoding and Decoding

import json

data = {"name": "Alice", "age": 30, "active": True}

# Python → JSON string
json_string = json.dumps(data, indent=2)
print(json_string)

# JSON string → Python
parsed = json.loads(json_string)
print(parsed["name"])   # Alice

See Python JSON for file-based reading and writing.

collections — Specialized Data Structures

from collections import Counter, defaultdict

# Count occurrences
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
counts = Counter(words)
print(counts)              # Counter({'apple': 3, 'banana': 2, 'cherry': 1})
print(counts.most_common(2))  # [('apple', 3), ('banana', 2)]

# Dict with default values
scores = defaultdict(int)
scores["Alice"] += 10
scores["Bob"] += 5
print(dict(scores))   # {'Alice': 10, 'Bob': 5}

See Python Collections Module for namedtuple, deque, and OrderedDict.

Creating Your Own Module

Basic Structure

Modules work best when they do one thing well. A good rule of thumb: if a group of functions share a theme, put them in their own file.

# mathutils.py

def clamp(value, minimum, maximum):
    """Restrict value to the range [minimum, maximum]."""
    return max(minimum, min(value, maximum))

def average(numbers):
    """Return the arithmetic mean of a list of numbers."""
    if not numbers:
        raise ValueError("Cannot average an empty list")
    return sum(numbers) / len(numbers)

def is_prime(n):
    """Return True if n is a prime number."""
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True
# main.py
from mathutils import clamp, average, is_prime

print(clamp(15, 0, 10))          # 10
print(average([2, 4, 6, 8]))     # 5.0
print(is_prime(17))              # True

Docstrings in Modules

Add a module-level docstring at the very top of the file. Tools like help() and documentation generators use it.

"""
mathutils.py — Utility functions for common mathematical operations.

Functions:
    clamp(value, minimum, maximum) -> number
    average(numbers) -> float
    is_prime(n) -> bool
"""

Module Variables: __all__

__all__ is a list of names that should be exported when someone does from module import *. It also serves as documentation about the module's public API.

# mathutils.py
__all__ = ["clamp", "average", "is_prime"]

def _helper():   # leading underscore marks it as private
    pass

Reloading a Module

Python caches imported modules in sys.modules. Importing the same module twice does not re-execute it — Python returns the cached version. During interactive development or debugging you can force a reload:

import importlib
import greetings

importlib.reload(greetings)

This is mostly needed in REPL sessions or Jupyter notebooks after editing a module file.

Common Gotchas

Circular Imports

If module_a imports module_b and module_b imports module_a, you get a circular import. Python can handle some circular imports, but they are confusing and often indicate a design problem. The fix is usually to restructure your code — move the shared logic into a third module, or delay the import to inside a function.

Shadowing a Standard Library Module

If you name your file math.py, random.py, or json.py, you will shadow the standard library module and break any code that imports it. Use specific, descriptive names for your own modules.

# BAD: naming your file math.py shadows the stdlib
# GOOD: name it mathutils.py or geometry.py

ImportError and ModuleNotFoundError

ModuleNotFoundError (a subclass of ImportError) means Python could not find the module anywhere on sys.path. Common causes:

  • A typo in the module name
  • The module is not installed (pip install <package-name>)
  • The module file is in a directory not on sys.path
try:
    import nonexistent_module
except ModuleNotFoundError as e:
    print(f"Import failed: {e}")
    # Import failed: No module named 'nonexistent_module'

Modules vs. Packages

A module is a single .py file. A package is a directory containing multiple modules and an __init__.py file. Packages let you build larger libraries with a hierarchical structure. See Python Packages for the full story.

Beyond the standard library, the Python ecosystem on PyPI has hundreds of thousands of packages. Install them with pip.

PackagePurpose
numpyNumerical computing, multi-dimensional arrays
pandasData analysis and manipulation
matplotlibData visualization and plotting
requestsHTTP requests made simple
flask / djangoWeb frameworks
scikit-learnMachine learning algorithms
pytestTesting framework

Practice

Practice
Which built-in variable tells you whether a Python file is being run directly or imported as a module?
Which built-in variable tells you whether a Python file is being run directly or imported as a module?
Was this page helpful?