Skip to main content

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:

  1. Sys Modules Cache: Checks if the module is already loaded.
  2. Built-in Modules: Checks standard libraries like os, sys, and json.
  3. Sys Path: Searches directories in sys.path, which includes your current directory and installed site-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
The Main Script Trap

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

Choosing an Import 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

FeatureAbsolute ImportRelative Import
Syntaxfrom package.module import funcfrom .module import func
ReadabilityHigh (clear path)Medium (context dependent)
RefactoringResilient to file movesBreaks when files move
Script ExecutionWorks everywhereFails in __main__ context
PEP 8 RecommendationPreferredAcceptable 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.