Skip to content

Python · Modules, Packages & Environments

Python Import System Explained — Modules, sys.path, Caching, and Absolute vs Relative Imports

3 min read Updated 2026-06-19 Share:

Practice The Import System interview questions

Python's import system, explained

import looks trivial until a circular import or a "module not found" error stops you cold. Underneath, importing is a well-defined process: find the module, load and execute it once, cache it, and bind a name. Knowing the steps makes import problems easy to diagnose.

What import actually does

The first time you import a module, Python finds it, executes its top-level code once, builds a module object, caches it, and binds a name in your namespace. Re-importing reuses the cache — the code does not run again.

# greet.py
print("greet module loading")
GREETING = "hello"

# main.py
import greet      # prints "greet module loading"
import greet      # prints nothing — already cached
print(greet.GREETING)

That "runs once" rule is why putting executable side effects at module top level can surprise you, and why the if __name__ == "__main__" guard exists.

sys.modules is the cache

Imported modules are stored in the sys.modules dict, keyed by name. Python checks it before searching the filesystem, which is what makes repeat imports instant.

import sys
import json
"json" in sys.modules      # True
sys.modules["json"]        # <module 'json' ...>

You can even force a reload with importlib.reload, but in normal code the cache is exactly what you want.

sys.path: where Python looks

To find a module, Python searches the directories in sys.path, in order: the script's directory (or cwd), then PYTHONPATH entries, then installed/standard-library locations.

import sys
for p in sys.path:
    print(p)        # first match wins

This is why a local file named random.py can shadow the standard library — your directory is searched first. Naming files after stdlib modules is a classic self-inflicted bug.

Absolute vs relative imports

Absolute imports name the full path from a top-level package and are the recommended default. Relative imports use leading dots to reference the current package, handy inside a package.

# absolute — clear and unambiguous
from myapp.utils.text import slugify

# relative — . is current package, .. is parent
from .text import slugify
from ..models import User

Relative imports only work inside a package (a module that was imported as part of one), not in a script run directly — a frequent source of "attempted relative import" errors.

import vs from import

import module binds the module name; from module import name binds the name directly. The latter is convenient but copies a reference at import time, so rebinding the original later won't be seen.

import math
math.pi                     # access through the module

from math import pi, sqrt   # bind names directly
sqrt(16)

from math import sqrt as square_root   # alias to avoid clashes

Avoid from module import * outside the REPL — it hides where names come from and can clobber locals.

Circular imports

If module A imports B while B imports A, one of them runs into a half-initialised module and some names won't exist yet. The fixes: restructure to remove the cycle, move the import inside the function that needs it (deferring it past module load), or import the module rather than its names.

# Instead of a top-level "from b import thing" that cycles:
def do_work():
    from b import thing      # imported lazily, after both modules finish loading
    return thing()

Recap

Importing finds, executes once, caches, and binds: top-level module code runs a single time, and sys.modules caches the result so re-imports are instant. Modules are located by searching sys.path in order (your directory first — beware shadowing stdlib names). Prefer absolute imports; relative (dotted) imports work only inside packages. from X import name binds names directly but copies references. Break circular imports by restructuring or deferring the import inside a function.

More ways to practice

The self-quiz is live. Get notified when mock interviews and new question packs drop.

or
Join our WhatsApp Channel