How can I do relative imports in Python?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Relative imports in Python work only inside packages, and most confusion comes from trying to use them in a file that is being executed as a top-level script. The syntax itself is simple. The tricky part is understanding how Python decides whether a module belongs to a package at import time.
What Relative Imports Mean
Relative imports use leading dots to describe a path relative to the current module.
The rules are:
- '
.means the current package' - '
..means the parent package' - '
...means go up another level'
These imports are resolved from the module's package name, not from the current working directory.
They Work Only Inside Packages
Suppose you have this structure:
Inside main.py, this is valid:
But it works only if main.py is imported or executed as part of the app package. If you run the file directly with python app/main.py, Python treats it as a top-level script, so it has no package context and the relative import fails.
Run Package Modules with -m
The usual fix is to run the module through Python's module mode.
That tells Python to load app.main as part of the app package, which gives relative imports the package context they need.
This is the key rule that explains most "attempted relative import with no known parent package" errors.
Prefer Absolute Imports at Package Boundaries
Relative imports are useful inside a package, but they are not always the clearest option. Absolute imports are often easier to read in larger projects.
A practical rule is:
- use relative imports for nearby internal modules when that improves locality
- use absolute imports when clarity matters more than brevity
Both can be valid. The important part is to keep the package structure coherent.
Avoid sys.path Hacks
A common but weak workaround is to modify sys.path so direct script execution can find siblings.
This may seem to fix the import error, but it makes the project more fragile and environment-dependent. In most cases, it is better to structure the code as a package and run it with python -m ....
Example Package Layout
Here is a small package that uses relative imports cleanly.
utils.py:
cli.py:
Run it like this:
That preserves the package context and keeps the relative import valid.
Common Pitfalls
- Running a package module directly as a script and expecting relative imports to work.
- Confusing the current working directory with the module's package path.
- Using
sys.pathmanipulation as a permanent fix instead of structuring the project properly. - Mixing absolute and relative imports inconsistently until the package layout becomes hard to reason about.
- Forgetting that relative imports only make sense for code that is part of a package.
Summary
- Relative imports use leading dots to refer to modules inside the same package hierarchy.
- They work only when Python knows the current module belongs to a package.
- Run package modules with
python -m package.moduleinstead of executing the file directly. - Prefer a clean package structure over
sys.pathhacks. - Use absolute or relative imports deliberately based on readability and package design.

