Question
Python Relative Imports Explained: Fixing "attempted relative import with no known parent package"
Question
I want to understand why Python raises this error:
ImportError: attempted relative import with no known parent package
Suppose I have this package structure:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
I created simple functions such as spam() and eggs() inside the appropriate modules and tried importing them from the console, but the relative imports did not work.
I have read multiple explanations of PEP 328, packages, and relative imports, but I still do not clearly understand:
- Why Python says
attempted relative import in non-package - What
no known parent packagemeans - What Python means by a package
- Why running a file directly often breaks relative imports
- How using
python -m ...solves the problem
In short, how should relative imports be used correctly in Python, and why does this error happen?
Short Answer
By the end of this page, you will understand what Python packages are, how relative imports work, why running a module directly often causes import errors, and how to use python -m correctly. You will also see practical examples of package layouts, import syntax, and the most common mistakes that lead to attempted relative import with no known parent package.
Concept
In Python, a relative import means importing something based on the current module's position inside a package.
For example:
from . import moduleY
from ..subpackage2 import moduleZ
The dots mean:
.= current package..= parent package...= grandparent package
For Python to resolve those dots, it must know where the current module lives inside the package hierarchy.
That is the key idea.
If Python runs a file as a plain script, that file is treated as a top-level module, usually with:
__name__ == "__main__"
In that situation, Python does not reliably know the module's package context, so a statement like this cannot be resolved:
from . import moduleY
Python then raises:
ImportError: attempted relative import with no known parent package
What is a package?
A package is a directory of Python modules that Python can treat as part of a module hierarchy.
Traditionally, a package contains an __init__.py file:
package/
__init__.py
That tells Python that the directory should be treated as a package. In modern Python, namespace packages can also exist without __init__.py, but for beginners, it is best to think of a package as:
- a folder of Python code
- usually containing
__init__.py - importable using dotted names like
package.moduleA
Why the error mentions a "non-package"
When Python says "non-package", it means the module being executed is not currently being treated as part of a package import path.
Even if the file physically sits inside a package folder, Python may still treat it like a standalone script if you launch it directly:
python package/subpackage1/moduleX.py
In that case, moduleX.py is not loaded as package.subpackage1.moduleX. It is loaded as a script, so relative imports fail.
Why -m helps
When you run a module with -m, Python loads it using its full package name:
python -m package.subpackage1.moduleX
Now Python knows:
- the module is
package.subpackage1.moduleX - its parent package is
package.subpackage1 - relative imports can be resolved correctly
That is why -m often fixes the problem instantly.
Mental Model
Think of a relative import like giving directions inside a building.
.means "this room"..means "go up one floor"
But those directions only work if you know where you currently are.
If someone drops you in a building and says only, "You are here," then go up one floor makes sense.
But if you are standing in an empty field with no building map, "go up one floor" is meaningless.
That is what happens with Python:
- When a module is run as part of a package, Python has the building map.
- When a file is run directly as a script, Python often loses that map.
So a relative import is like saying:
Go to the sibling room next to me.
Python answers:
I do not know what building you are in, so I cannot follow that instruction.
That is the meaning of no known parent package.
Syntax and Examples
Basic relative import syntax
from . import moduleY
from .moduleY import spam
from ..subpackage2 import moduleZ
from ..subpackage2.moduleZ import eggs
Example package
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
Example code
package/subpackage1/moduleY.py
def spam():
return "spam from moduleY"
package/subpackage1/moduleX.py
from .moduleY import spam
print(spam())
Wrong way to run it
python package/subpackage1/moduleX.py
This often fails because moduleX.py is being run as a standalone script, not as part of package.subpackage1.
Correct way to run it
Run this from the directory containing package:
python -m package.subpackage1.moduleX
Now Python knows the full module path and can resolve:
from .moduleY import spam
Absolute import alternative
You can also write:
from package.subpackage1.moduleY import spam
Absolute imports are often easier to read in larger projects, especially when files may be executed in different contexts.
Step by Step Execution
Consider this file:
package/subpackage1/moduleX.py
from .moduleY import spam
print(spam())
And this file:
package/subpackage1/moduleY.py
def spam():
return "hello"
Case 1: Run the file directly
python package/subpackage1/moduleX.py
What happens:
- Python starts executing
moduleX.pyas a script. - Its module name becomes
__main__. - Python does not treat it as
package.subpackage1.moduleX. - The line
from .moduleY import spammeans "importmoduleYfrom my current package". - But Python does not know the current package.
- It raises:
ImportError: attempted relative import with no known parent package
Case 2: Run with -m
python -m package.subpackage1.moduleX
What happens:
- Python starts from the parent directory of
package. - It loads
moduleXusing the full namepackage.subpackage1.moduleX. - Python now knows the parent package is
package.subpackage1. - The relative import
from .moduleY import spamcan be resolved. spam()is imported and called.- Output:
hello
Important detail
The problem is usually not the import statement itself.
The problem is how the module was executed.
Real World Use Cases
Relative imports are useful when code is organized into packages and subpackages.
Common scenarios
- Utility modules inside a package
- Example:
from .helpers import format_date
- Example:
- Feature folders in web apps
- Example: routes importing validators or services from the same package
- Data processing packages
- One module imports parsers, cleaners, or exporters from nearby modules
- Libraries distributed on PyPI
- Internal modules often use package-relative imports to reference sibling files
Example: API package
myapp/
api/
__init__.py
routes.py
validators.py
routes.py might contain:
from .validators import validate_user_payload
This keeps imports tied to the package structure instead of depending on the current working directory.
When relative imports help most
- When modules in the same package need to talk to each other
- When you want to avoid repeating a long absolute path
- When code may be moved within the project without changing every import
Real Codebase Usage
In real projects, developers usually combine absolute imports for clarity and relative imports for internal package relationships.
Common patterns
1. Internal helpers
from .utils import parse_config
from .errors import ConfigError
This is common when files are tightly related inside one package.
2. Absolute imports at package boundaries
from myapp.database.connection import connect
This makes it clear where code comes from, especially in larger applications.
3. Guarded script entry points
Instead of running package files directly, developers often add an entry point:
def main():
print("Run app")
if __name__ == "__main__":
main()
Then they execute it with:
python -m package.subpackage1.moduleX
4. Separation between library code and runnable code
A common pattern is:
- package modules contain reusable logic
- a separate top-level script calls into the package
Example:
project/
run_app.py
package/
__init__.py
service.py
run_app.py
from package.service import start
start()
This avoids many relative import issues.
5. Test code and imports
Tests often fail when developers run files from the wrong directory. Real codebases usually run tests from the project root so imports resolve consistently.
Common Mistakes
1. Running a package module as a plain script
Broken:
python package/subpackage1/moduleX.py
If moduleX.py contains:
from .moduleY import spam
it may fail because Python does not know its package context.
Avoid it by running:
python -m package.subpackage1.moduleX
2. Forgetting the package root
If you run -m from the wrong directory, Python may not find the package.
Suppose your structure is:
project/
package/
__init__.py
You should usually run this from project/, not from inside package/:
python -m package.moduleA
3. Mixing direct execution and package imports
Broken pattern:
# inside moduleX.py
from .moduleY import spam
if __name__ == "__main__":
print(spam())
Then running:
python moduleX.py
This often fails if moduleX.py depends on package-relative imports.
Avoid it by either:
- running with
-m - using a separate launcher script
- using absolute imports where appropriate
4. Confusing filesystem layout with import context
A file being inside a package folder is not enough by itself.
Python must import or execute it as part of that package.
5. Using relative imports in top-level scripts
Broken:
from .helpers import func
This only works inside a package module, not in a standalone top-level script.
6. Shadowing package names
If you name a file the same as a package or standard library module, imports can become confusing.
Examples:
email.pyjson.pypackage.py
Avoid using names that conflict with existing modules.
Comparisons
| Concept | What it means | Example | Best used when |
|---|---|---|---|
| Relative import | Import based on current package position | from .moduleY import spam | Importing nearby modules inside the same package |
| Absolute import | Import from the full package path | from package.subpackage1.moduleY import spam | Large projects where clarity matters |
| Direct script execution | Run a file by path | python package/subpackage1/moduleX.py | Simple standalone scripts |
Module execution with -m | Run using module path | python -m package.subpackage1.moduleX | Package modules that use relative imports |
Relative imports vs absolute imports
Relative imports
Pros:
- shorter inside a package
- easier when moving a whole package subtree
Cons:
- harder for beginners to understand
- break when the module is run incorrectly
Absolute imports
Pros:
- clear and explicit
- easier to search and read in large codebases
Cons:
- longer to write
- may need updates if the top-level package name changes
Package module vs standalone script
| Situation | Relative imports work? | Why |
|---|---|---|
Imported as package.subpackage1.moduleX | Yes | Python knows the parent package |
Run as python package/subpackage1/moduleX.py | Usually no | Python treats it as a standalone script |
Run as python -m package.subpackage1.moduleX | Yes | Python loads it with full package context |
Cheat Sheet
Quick rules
- Relative imports use dots:
.current package..parent package
- Relative imports only work when Python knows the module's package name.
- Running a file directly often removes that package context.
- Use
python -m package.moduleinstead ofpython path/to/file.pyfor package modules.
Common syntax
from . import moduleY
from .moduleY import spam
from ..subpackage2 import moduleZ
from package.subpackage1.moduleY import spam # absolute import
Typical package layout
project/
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
Correct run command
From project/:
python -m package.subpackage1.moduleX
Common error meaning
ImportError: attempted relative import with no known parent package
Meaning:
- Python saw a relative import like
from .moduleY import spam - but it did not know what package the current module belongs to
Good practice
- Use absolute imports for clarity in bigger projects
- Use relative imports for nearby internal modules when appropriate
- Do not run package files directly if they depend on relative imports
- Keep runnable entry points separate when possible
FAQ
Why does Python say "attempted relative import with no known parent package"?
Because the module uses a relative import like from .x import y, but Python does not know what package the current file belongs to.
What is a parent package in Python?
It is the package that contains the current module. For example, the parent package of package.subpackage1.moduleX is package.subpackage1.
Why does running a file directly break relative imports?
Because Python usually loads that file as __main__ instead of by its full package name, so the package hierarchy is lost.
How does python -m fix relative imports?
It runs the module by its dotted module name, so Python knows its package context and can resolve relative imports.
Do I always need __init__.py for a package?
In modern Python, not always, because namespace packages exist. But for most beginner learning and many projects, including __init__.py makes package behavior clearer.
Should I use relative or absolute imports?
Use absolute imports when you want clarity and consistency. Use relative imports for nearby internal modules when that makes the package easier to maintain.
Can a top-level script use relative imports?
Usually no. Relative imports are meant for modules inside packages, not standalone scripts.
What is the safest project structure for avoiding this error?
Keep application logic inside packages, and run modules with python -m ... or from a separate top-level entry script.
Mini Project
Description
Build a small Python package with two modules in the same subpackage and one runnable module that uses a relative import correctly. This project demonstrates the exact situation that causes the attempted relative import with no known parent package error and shows the proper way to run the code.
Goal
Create a package that uses relative imports successfully and run it with python -m from the project root.
Requirements
- Create a package directory with
__init__.pyfiles. - Add one helper module that defines a function.
- Add one runner module that imports the helper with a relative import.
- Print the helper function result when the runner module executes.
- Run the project using
python -mfrom the parent directory of the package.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.