How to Use Absolute and Relative Imports in Python
Organizing code into modules and packages is a cornerstone of Python development. However, knowing how to import that code can be confusing. This guide breaks down the two main import styles, absolute and relative, and explains why absolute imports are almost always the better choice.
How Python Finds Modules
When you write import math, Python searches for the module in this order:
- Sys Modules Cache: Checks if the module is already loaded.
- Built-in Modules: Checks standard libraries like
os,sys, andjson. - Sys Path: Searches directories in
sys.path, which includes your current directory and installedsite-packages.
Using Absolute Imports
An absolute import specifies the full path from the project's root directory to the module. It does not matter where the current file is located; only the project structure matters.
Example Project Structure
my_project/
├── main.py
└── ecommerce/
├── __init__.py
├── database.py
└── payments/
├── __init__.py
└── stripe.py
To import the database module inside stripe.py, use the full path:
from ecommerce import database
def process_payment():
database.save_transaction()
You can also import specific functions or classes:
from ecommerce.database import save_transaction, get_user
def process_payment():
user = get_user()
save_transaction()
Benefits of Absolute Imports
- Clarity: The full path shows exactly where the module lives.
- Robustness: Moving files to different folders does not break import statements.
- Consistency: Works the same way whether running as a script or importing as a module.
Using Relative Imports
A relative import uses dot notation to define where the module is relative to the current file:
.refers to the current directory..refers to the parent directory...refers to the grandparent directory
Example Usage
Inside stripe.py (located in ecommerce/payments/), you can import database.py (located in ecommerce/) like this:
from .. import database
def process_payment():
database.save_transaction()
To import from a sibling module in the same directory:
from . import utils
from .helpers import format_currency
Relative imports fail when you run the file directly as a script:
python stripe.py
This produces the error:
ImportError: attempted relative import with no known parent package
When running a script directly, Python names it __main__ and does not recognize it as part of a package. Relative imports only work inside imported packages.
Running Modules Correctly
To run a module that uses relative imports, use the -m flag:
python -m ecommerce.payments.stripe
This tells Python to treat the file as part of the package structure.
Best Practices
Following PEP 8 guidelines ensures consistent and maintainable code.
Import Ordering
Group imports in this order, with a blank line between each group:
# 1. Standard library imports
import os
import sys
from datetime import datetime
# 2. Third-party imports
import requests
from sqlalchemy import create_engine
# 3. Local application imports
from ecommerce import database
from ecommerce.payments import stripe
When to Use Each Style
- Use absolute imports as your default choice for clarity and maintainability.
- Use relative imports only within tightly coupled package internals where the package name might change but the internal structure remains stable.
Common Import Patterns
Importing Multiple Items
# Absolute
from ecommerce.database import (
save_transaction,
get_user,
update_inventory,
)
# Relative
from ..database import (
save_transaction,
get_user,
update_inventory,
)
Aliasing Imports
from ecommerce.payments.stripe import StripePaymentProcessor as PaymentProcessor
import numpy as np
Conditional Imports
try:
import ujson as json
except ImportError:
import json
Comparison Summary
| Feature | Absolute Import | Relative Import |
|---|---|---|
| Syntax | from package.module import func | from .module import func |
| Readability | High (clear path) | Medium (context dependent) |
| Refactoring | Resilient to file moves | Breaks when files move |
| Script Execution | Works everywhere | Fails in __main__ context |
| PEP 8 Recommendation | Preferred | Acceptable for complex packages |
Summary
Absolute imports provide clarity, consistency, and resilience to code refactoring, making them the recommended choice for most Python projects. Relative imports serve a purpose in complex packages with stable internal structures but should be used sparingly. Following PEP 8 guidelines for import ordering and grouping keeps your codebase maintainable and readable.