Python Modules and Packages: Complete Guide

Published on: July 10, 2026
Reading time: 5 minutes
Caixas empilhadas

As a Python project grows, keeping every function and class in one file becomes difficult. Python modules and packages solve that problem by dividing code into focused, reusable parts.

A module is usually one .py file. A package is a directory that groups related modules. Together, they help you create clearer projects, reuse code, write tests, and collaborate without turning one script into thousands of lines.

What is a Python module?

Any Python file can act as a module. Suppose a project contains a file named calculator.py:

# calculator.py

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

PI = 3.14159

Another file can import and use it:

# main.py
import calculator

print(calculator.add(10, 5))
print(calculator.PI)

The module name is the filename without .py. The official Python modules tutorial explains how Python loads files and creates module namespaces.

Different import styles

The regular import form keeps the module name visible:

import calculator
result = calculator.add(4, 8)

You can import specific names:

from calculator import add, subtract
print(add(4, 8))

Aliases are useful for long or conventional names:

import calculator as calc
print(calc.subtract(20, 3))

Avoid from module import *. It hides where names come from and can silently overwrite variables. Clear imports support the naming and organization rules discussed in the PEP 8 guide.

How Python finds modules

When Python sees an import, it checks several locations, including the current project, the standard library, installed packages, and directories listed in sys.path.

import sys

for folder in sys.path:
    print(folder)

A common mistake is naming your own file after a standard or third-party module. A file called random.py, json.py, or requests.py can shadow the real library and cause confusing import errors. The guide to fixing ModuleNotFoundError covers environment and path problems in detail.

What is a Python package?

A package is a directory containing modules that belong together. A small store application might use this structure:

store_app/
├── main.py
└── store/
    ├── __init__.py
    ├── products.py
    ├── orders.py
    └── reports.py

The store directory is the package. Each Python file inside it is a submodule.

# store/products.py

def calculate_total(price, quantity):
    return price * quantity
# main.py
from store.products import calculate_total

print(calculate_total(19.90, 3))

What does __init__.py do?

The __init__.py file marks a regular package and can define the public interface that users import. It may be empty, but it can also re-export selected names:

# store/__init__.py
from .products import calculate_total

__all__ = ["calculate_total"]

Now the application can use:

from store import calculate_total

Keep __init__.py lightweight. Running database connections, network requests, or expensive calculations during import makes applications slow and unpredictable.

Absolute and relative imports

An absolute import begins at the top-level package:

from store.products import calculate_total

A relative import uses dots to refer to nearby modules:

# store/reports.py
from .products import calculate_total

Absolute imports are often easier to understand in application code. Relative imports can be convenient inside a cohesive package. Consistency is more important than mixing styles without a reason.

Using __name__ and running a module

Every module has a __name__ variable. When a file runs directly, its value is "__main__". When imported, it contains the module name.

# temperature.py

def celsius_to_fahrenheit(value):
    return value * 9 / 5 + 32

if __name__ == "__main__":
    print(celsius_to_fahrenheit(25))

This guard prevents demonstration or command-line code from running merely because the module was imported.

Packages can also be executed with python -m package.module. This approach preserves the import context and often avoids path errors.

Designing a useful project structure

A beginner-friendly application might look like this:

expense_tracker/
├── README.md
├── pyproject.toml
├── src/
│   └── expense_tracker/
│       ├── __init__.py
│       ├── models.py
│       ├── storage.py
│       └── cli.py
└── tests/
    ├── test_models.py
    └── test_storage.py

The src layout helps prevent accidental imports from the project folder. Tests live separately but import the installed package. The article about unit testing in Python shows how this separation improves test organization.

Modules, packages, libraries, and distributions

These terms are related but not identical:

  • Module: one importable Python file.
  • Package: an importable directory of modules.
  • Library: a general term for reusable code.
  • Distribution: the installable project published to a package index.

A distribution can contain one or more packages. The guide to Python libraries explains how reusable code is installed and used, while the tutorial on creating an installable package covers packaging metadata and builds.

A practical example

Consider a package that formats customer data:

customer_tools/
├── __init__.py
├── names.py
└── validation.py
# customer_tools/names.py

def normalize_name(name):
    return " ".join(part.capitalize() for part in name.split())
# customer_tools/validation.py

def is_valid_email(email):
    return "@" in email and "." in email.rsplit("@", 1)[-1]
# customer_tools/__init__.py
from .names import normalize_name
from .validation import is_valid_email
from customer_tools import normalize_name, is_valid_email

name = normalize_name("  aLEX johnSON ")
email = "[email protected]"

print(name)
print(is_valid_email(email))

This organization gives each module one responsibility and creates a simple public interface.

Avoiding circular imports

A circular import happens when module A imports module B while module B imports module A. Python may encounter a partially initialized module and raise an error.

Common solutions include moving shared definitions into a third module, importing a dependency inside a function only when necessary, or redesigning responsibilities so modules do not depend on each other in both directions.

package/
├── common.py
├── users.py
└── orders.py

Both users.py and orders.py can import shared types from common.py without importing each other.

Common mistakes

Running an internal file directly

Executing python package/module.py can break relative imports. Run it from the project root with python -m package.module.

Depending on the current working directory

Build file paths from __file__ or use pathlib rather than assuming the terminal always starts in one folder.

Putting unrelated code in one package

A package should represent a coherent feature or domain. Split independent concerns into separate packages.

Creating too many tiny modules

Organization should reduce complexity, not create a maze. A module with one trivial function is not automatically better than a clear, focused file containing several related functions.

Best practices

  • Use lowercase module and package names.
  • Give each module a clear responsibility.
  • Keep imports at the top unless a local import solves a specific problem.
  • Expose a small, intentional public API.
  • Avoid side effects during import.
  • Use virtual environments to isolate dependencies. The venv tutorial explains the workflow.
  • Add tests before reorganizing a mature project.

Conclusion

Python modules and packages turn a growing script into a maintainable application. Begin by moving related functions into modules, group those modules into packages, use explicit imports, and keep dependencies flowing in one clear direction.

For deeper reference, review the official Python import system documentation. A small project organized into two or three modules is the best place to practice before designing a larger installable package.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    logo do python com objetos abaixo do logo
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Object-Oriented Python: Classes and Objects

    Learn object-oriented Python with classes, objects, attributes, methods, constructors, inheritance, composition, encapsulation, properties, and practical examples.

    Ler mais

    Tempo de leitura: 6 minutos
    10/07/2026
    Programação assíncrona com asyncio em Python
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Python asyncio: A Practical Beginner’s Guide

    Learn Python asyncio with coroutines, await, tasks, TaskGroup, timeouts, cancellation, queues, locks, error handling, and blocking work.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Uso de expressões regulares regex para manipulação de texto em Python
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Python Regex: Complete Regular Expressions Guide

    Learn Python regex with re.search, fullmatch, findall, groups, quantifiers, substitutions, flags, compiled patterns, and practical examples.

    Ler mais

    Tempo de leitura: 7 minutos
    10/07/2026
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Python Decorators Explained: Practical Guide

    Learn Python decorators with practical examples, wrappers, arguments, functools.wraps, class decorators, common use cases, and mistakes to avoid.

    Ler mais

    Tempo de leitura: 8 minutos
    21/05/2026
    Uso do super em Python para resolver problemas de herança
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Use super() in Python and Fix Inheritance Errors

    Learn how to use super() in Python for parent methods, multiple inheritance, MRO, *args, **kwargs, and cleaner object-oriented code.

    Ler mais

    Tempo de leitura: 8 minutos
    19/05/2026
    Criando instalador EXE com ícone personalizado em Python
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    How to Create a exe Installer with a Custom Icon in Python

    Learn how to package any Python script into a standalone .exe file with a custom icon using PyInstaller. Step-by-step guide

    Ler mais

    Tempo de leitura: 11 minutos
    09/05/2026