What is a module in Python?
In Python, a module is a file containing Python code — functions, classes, variables and executable statements — that you can reuse in other programs. A module has a .py extension and is one of the fundamental building blocks of code organization in Python. If you want to master modules and many other essential concepts, our comprehensive Python course will guide you step by step.
The module system allows you to break a large program into smaller files that are more readable and easier to maintain. Instead of writing everything in a single file, you group related functionalities into separate modules, then import them wherever you need them. This is the very essence of modularity in programming.
A Python module is simply a .py file. If you have already written a Python script, you have already created a module without knowing it!
Detailed definition of a module
A module is a logical unit of code that encapsulates definitions and statements. Python distinguishes three main categories of modules:
| Module type | Description | Example |
|---|---|---|
| Built-in module | Shipped with the Python installation | math, os, sys, json |
| Third-party module | Installed via pip from PyPI | requests, numpy, flask |
| Custom module | Created by the developer | my_module.py |
When you import a module, Python executes all the code contained in that file once, then caches the result. Subsequent imports of the same module reuse this cache, which is both efficient and performant.
A module can contain:
- Functions defined with the def keyword
- Classes defined with the class keyword
- Variables and constants
- Executable code (which runs upon import)
- docstring to document the module
Importing a module in Python
Python offers several syntaxes for importing a module. Each has its advantages and use cases. Let's look at them in detail.
The import statement
The simplest way to import a module is to use the import keyword followed by the module name:
import math
# Usage with the module prefix
result = math.sqrt(144)
print(result) # 12.0
pi = math.pi
print(pi) # 3.141592653589793With this syntax, you must always prefix the module's elements with its name (here math.). This is the most explicit method and the one that avoids name conflicts.
The from ... import statement
If you only need certain elements from a module, you can import them directly:
from math import sqrt, pi
# Direct usage, without prefix
result = sqrt(144)
print(result) # 12.0
print(pi) # 3.141592653589793This syntax is more concise, but can lead to conflicts if two modules export identical names.
Importing with an alias
You can rename a module during import using the as keyword:
import numpy as np
import pandas as pd
array = np.array([1, 2, 3, 4, 5])
print(array.mean()) # 3.0Aliases like np for NumPy or pd for Pandas are widely adopted conventions in the Python community.
Importing all elements with *
from math import *
# All elements from math are directly accessible
print(sqrt(25)) # 5.0
print(cos(0)) # 1.0Importing with * is strongly discouraged in production. It pollutes the namespace, makes the code hard to read and can cause unpredictable name conflicts. Always prefer explicit imports.
Note that the __all__ variable allows you to control which elements are exported when a user uses from module import *.
Creating your own module
Creating a module in Python is extremely simple: just create a .py file and write code in it. Let's see a concrete example.
Step 1: Create the module file
Create a file named calculator.py:
"""Calculator module - Basic mathematical operations."""
PI = 3.14159265358979
def add(a, b):
"""Return the sum of a and b."""
return a + b
def subtract(a, b):
"""Return the difference between a and b."""
return a - b
def multiply(a, b):
"""Return the product of a and b."""
return a * b
def divide(a, b):
"""Return the quotient of a divided by b."""
if b == 0:
raise ValueError("Division by zero is not allowed")
return a / b
Step 2: Use the module
In another Python file located in the same directory, you can now import and use your module:
import calculator
result = calculator.add(10, 5)
print(result) # 15
quotient = calculator.divide(20, 4)
print(quotient) # 5.0
print(calculator.PI) # 3.14159265358979You can also use from ... import:
from calculator import add, divide
print(add(7, 3)) # 10
print(divide(15, 3)) # 5.0
The __name__ variable and the main pattern
The special variable __name__ plays an essential role in modules. When Python executes a file directly, it assigns the value "__main__" to __name__. When the file is imported as a module, __name__ takes the value of the module's name.
This mechanism allows you to create code that only runs when the file is executed directly:
# calculator.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
if __name__ == "__main__":
# This block only runs if the file is executed directly
print("Calculator tests:")
print(add(2, 3)) # 5
print(subtract(10, 4)) # 6
print("All tests pass!")The if __name__ == "__main__" pattern is an essential convention in Python. It allows you to make a module both importable and independently executable.
Packages: modules in folders
As your project grows, you will need to organize your modules into folders. In Python, a folder containing an __init__ file is called a package.
Here is a typical package structure:
my_project/
│
├── main.py
└── utils/
├── __init__.py
├── text.py
├── math_utils.py
└── files.pyThe __init__.py file can be empty or contain package initialization code. It tells Python that the folder should be treated as a package:
# utils/__init__.py
from .text import clean_text
from .math_utils import calculate_average
__all__ = ["clean_text", "calculate_average"]You can then import from the package:
# main.py
from utils import clean_text, calculate_average
from utils.files import read_file
clean = clean_text(" Hello world ")
average = calculate_average([10, 20, 30])
The most useful built-in modules
Python ships with an extremely rich standard library. Here are the most commonly used built-in modules:
| Module | Purpose | Usage example |
|---|---|---|
os | Interaction with the operating system | os.path.exists("file.txt") |
sys | System parameters and functions | sys.argv, sys.exit() |
json | Reading/writing JSON data | json.loads(), json.dumps() |
datetime | Date and time manipulation | datetime.now() |
random | Random number generation | random.randint(1, 100) |
re | Regular expressions | re.match(), re.findall() |
collections | Advanced data structures | OrderedDict, namedtuple |
pathlib | File path manipulation | Path("folder/file.txt") |
Let's see a concrete example using several built-in modules:
import os
import json
import datetime
# Check if a file exists
if os.path.exists("config.json"):
# Read and parse the JSON file
with open("config.json", "r") as f:
config = json.load(f)
print(f"Configuration loaded: {config}")
else:
# Create a default configuration
config = {
"app_name": "MyApp",
"version": "1.0",
"creation_date": str(datetime.datetime.now())
}
with open("config.json", "w") as f:
json.dump(config, f, indent=4)
print("Default configuration created")
Installing and using third-party modules
Beyond the standard library, the Python ecosystem has hundreds of thousands of third-party modules available on PyPI (Python Package Index). You install them with pip:
# Installation from the terminal
pip install requests
pip install numpy pandas
pip install flaskOnce installed, a third-party module is used exactly like a built-in module:
import requests
response = requests.get("https://api.github.com")
if response.status_code == 200:
data = response.json()
print(f"GitHub API accessible")
else:
print(f"Error: {response.status_code}")It is recommended to use a virtual environment (venv) to isolate each project's dependencies. This prevents version conflicts between your different projects.
How Python finds modules
When you write import my_module, Python looks for the module in a specific order:
- The module cache: if the module has already been imported, Python retrieves it from
sys.modules. - Built-in modules: Python checks if it is a built-in module (like
sysormath). - The search path
sys.path: Python goes through the directories listed insys.path, which includes:- The directory of the currently running script
- The directories defined by the
PYTHONPATHenvironment variable - The default installation directories (site-packages)
You can inspect the search path:
import sys
for path in sys.path:
print(path)And even add a custom directory:
import sys
sys.path.append("/path/to/my/modules")
import my_custom_module
Best practices for modules
To write clean and maintainable Python code, here are the best practices to follow regarding modules:
- Place all your imports at the top of the file: this is the PEP 8 convention. Imports should be grouped in this order: standard modules, third-party modules, local modules, with a blank line between each group.
- Avoid
from module import *: this syntax makes the code hard to understand and can cause name conflicts. - Always use the
if __name__ == "__main__"pattern: this makes your modules both importable and executable. - Define __all__: in your public modules, use the
__all__variable to explicitly control what is exported. - Document your modules: add a docstring at the very beginning of the file to explain the module's purpose.
- Name your modules in lowercase: according to PEP 8, module names should be short, lowercase, and underscores are acceptable if it improves readability.
- Avoid circular imports: if module A imports module B and B imports A, you will get errors. Restructure your code to eliminate these cyclic dependencies.
Here is an example of a file following all these conventions:
"""User management module.
This module provides functions to create, read,
update and delete users.
"""
# Standard modules
import os
import json
from datetime import datetime
# Third-party modules
import requests
# Local modules
from .database import connection
__all__ = ["create_user", "get_user"]
def create_user(name, email):
"""Create a new user.
Args:
name: The user's name.
email: The user's email address.
Returns:
dict: The created user's information.
"""
user = {
"name": name,
"email": email,
"creation_date": str(datetime.now())
}
return user
def get_user(identifier):
"""Retrieve a user by their identifier."""
# Retrieval logic...
pass
if __name__ == "__main__":
# Quick tests
user = create_user("Alice", "alice@example.com")
print(user)
Reloading a module
When working in interactive mode (in a Python terminal or a Jupyter notebook), a module is only imported once. If you modify the source file, the changes will not be taken into account automatically. To force a reload, use importlib.reload():
import importlib
import my_module
# After modifying the my_module.py file
importlib.reload(my_module)
# The changes are now taken into account
my_module.my_function()Module reloading is useful for interactive development, but it can cause unexpected behavior in complex programs. Prefer restarting your program rather than reloading modules in production.
Dynamic exploration of a module
Python offers several tools to explore the contents of a module at runtime:
import math
# List all attributes of the module
print(dir(math))
# Get help on the module
help(math)
# Get help on a specific function
help(math.sqrt)
# Check the module's file path
print(math.__file__)
# Read the module's docstring
print(math.__doc__)The print function combined with dir() is an excellent way to quickly discover what a module has to offer.
Frequently asked questions
What is the difference between a module and a package in Python?
A module is a single .py file containing Python code. A package is a folder containing an __init__ file and one or more modules. The package allows you to organize modules hierarchically. For example, utils/text.py is a module inside the utils package. You can think of a package as a folder of modules, and a module as an individual file.
How do you fix the ModuleNotFoundError error?
This error means that Python cannot find the module you are trying to import. First check that the module is properly installed (with pip list for third-party modules). Then make sure your file is in a directory listed in sys.path. If you are using a virtual environment, verify that it is properly activated. Finally, check that the module name is correctly spelled — Python is case-sensitive.
Can you import a module located in another directory?
Yes, you have several options. You can add the directory to sys.path, set the PYTHONPATH environment variable, or use relative imports within a package. The cleanest solution is to structure your project as a package with appropriate __init__.py files and install your package locally with pip install -e ..
How can you learn to properly organize your modules in Python?
Mastering modules and Python project architecture is achieved through practice and structured learning. We recommend following our dedicated Python course on Believemy, which covers modules, packages, code organization best practices and much more in depth. You will find hands-on exercises to help you progress quickly.