Question
Relative Imports in Python 3: Why They Work Sometimes and Fail Other Times
Question
I want to import a function from another Python file in the same directory.
Usually, one of these import statements works:
from .mymodule import myfunction
or
from mymodule import myfunction
But the other form often fails with one of these errors:
ImportError: attempted relative import with no known parent package
ModuleNotFoundError: No module named 'mymodule'
SystemError: Parent module '' not loaded, cannot perform relative import
Why does this happen, and how does Python decide which import style is valid?
Short Answer
By the end of this page, you will understand the difference between relative imports and absolute imports in Python 3, why they behave differently depending on how a file is run, and how to structure your code so imports work reliably in real projects.
Concept
In Python, imports are not based only on file location. They also depend on how Python sees your code at runtime.
There are two common styles involved here:
from mymodule import myfunction
This is usually treated as an absolute import. Python looks for mymodule in places such as:
- the current import path (
sys.path) - installed packages
- the project root, depending on how the program was started
And:
from .mymodule import myfunction
This is a relative import. The dot means:
- "start from the current package"
- import
mymodulefrom the same package as this file
The key idea is that relative imports only work when the file is part of a package.
Why this matters
In real programs, Python modules are often organized into packages:
project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ └── mymodule.py
If main.py is imported as part of package app, then this works:
from .mymodule import myfunction
But if you run main.py directly like this:
python main.py
then Python treats it as a top-level script, not as part of package app. In that case, . has no package context, so the relative import fails.
Why absolute imports also sometimes fail
This import:
from mymodule import myfunction
works only if Python can find mymodule on its import path.
If your file is inside a package, Python may expect you to refer to the full package path instead, such as:
from app.mymodule import myfunction
So the same two files can behave differently depending on:
- where you run Python from
- whether the file is executed directly or imported
- whether the folder is treated as a package
- what entries exist in
sys.path
That is why one form sometimes works and the other fails.
Mental Model
Think of Python imports like giving directions to a building.
- An absolute import is like giving the full street address.
- Example: "Go to
app.mymodule."
- Example: "Go to
- A relative import is like saying, "From where I am now, go next door."
- Example:
from .mymodule import myfunction
- Example:
The problem is that "next door" only makes sense if Python knows where you currently are in the package structure.
If a file is run directly, Python often says, in effect:
- "I know this is a script"
- "I do not know its package neighborhood"
So a relative import like .mymodule becomes meaningless.
A useful rule of thumb:
- Relative imports need package context
- Absolute imports need a correct import path
Syntax and Examples
Core syntax
Absolute import
from mymodule import myfunction
Or, inside a package-based project:
from app.mymodule import myfunction
Relative import
from .mymodule import myfunction
Parent-package relative import
from ..utils import helper
This means "go up one package level, then import utils."
Example project
project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ └── mymodule.py
mymodule.py:
def myfunction():
return "Hello from mymodule"
main.py:
from .mymodule import myfunction
print(myfunction())
This works when main.py is executed as a module from the project root:
python -m app.main
Why? Because Python now knows main.py belongs to the app package.
Example using absolute import
main.py:
from app.mymodule import myfunction
print(myfunction())
This also works when run from the project root:
python -m app.main
and often also when imported by other code in the project.
Beginner-friendly takeaway
If your code is inside a package, prefer imports that match the package structure. In many real projects, that means using:
from app.mymodule import myfunction
or running package code with:
python -m app.main
instead of running files directly from inside the package.
Step by Step Execution
Consider this structure:
project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ └── mymodule.py
mymodule.py:
def myfunction():
return 42
main.py:
from .mymodule import myfunction
result = myfunction()
print(result)
What happens when you run this?
Case 1: Run directly
python app/main.py
Step by step:
- Python starts
main.pyas the top-level script. - Its module name becomes something like
__main__. - Python does not treat it as part of package
app. - The statement
from .mymodule import myfunctionasks for a relative import. - Relative import needs a known parent package.
- No parent package is known.
- Python raises:
ImportError: attempted relative import with no known parent package
Case 2: Run as a module
python -m app.main
Step by step:
- Python starts from the project root.
- It loads
app.mainas a module inside packageapp. - Now Python knows the parent package is
app. from .mymodule import myfunctionmeans "importmymodulefromapp."- Python finds
app/mymodule.py. myfunction()runs.- Output is:
42
This is the same code, but a different execution context. That context changes whether the import is valid.
Real World Use Cases
Package-based applications
Large Python applications are usually split into packages:
- API routes
- database code
- utility modules
- configuration modules
Relative imports can help connect modules inside the same package.
Reusable libraries
When building a library, modules often import nearby helpers:
from .helpers import parse_data
from .config import DEFAULT_TIMEOUT
This makes it clear those modules belong to the same package.
Command-line tools
CLI tools often fail with import errors when developers run a file directly instead of running the package correctly.
For example, this may fail:
python tool/main.py
while this works:
python -m tool.main
Test suites
Tests often expose import problems because they may run from a different working directory. Using a clean package structure and consistent imports helps avoid environment-specific bugs.
Web applications
Framework-based apps often rely on package imports across folders such as:
modelsservicesroutesutils
Understanding import rules helps you avoid fragile code that only works when started from one exact folder.
Real Codebase Usage
In real codebases, developers usually avoid import confusion by following a few practical patterns.
1. Use a clear package structure
project/
├── myapp/
│ ├── __init__.py
│ ├── api.py
│ ├── services.py
│ └── utils.py
Then import using package-aware paths.
2. Prefer absolute imports for readability
Many teams prefer:
from myapp.utils import helper
because it is explicit and easier to understand in larger projects.
3. Use relative imports for closely related modules
Some projects use relative imports within a package:
from .utils import helper
This can be convenient when refactoring package names, but it depends on code being run inside package context.
4. Avoid running package files directly
Instead of:
python myapp/api.py
use:
python -m myapp.api
This is a very common real-project rule.
5. Keep entry points separate
A common pattern is to have a top-level runner file:
project/
├── run.py
├── myapp/
│ ├── __init__.py
│ └── main.py
run.py:
from myapp.main import start
start()
This avoids directly executing files inside the package.
6. Avoid manually editing sys.path
Beginners sometimes fix imports by adding folders to sys.path. This may work temporarily, but it usually makes code harder to maintain and test.
Common Mistakes
1. Running a package module as a plain script
Broken example:
python app/main.py
with:
from .mymodule import myfunction
Why it fails:
- Python does not know
main.pybelongs to packageapp
Better:
python -m app.main
2. Assuming "same directory" is enough
Broken thinking:
- "These files are next to each other, so import should always work."
In Python, imports depend on module/package context, not just physical file placement.
3. Using absolute imports without the package name
Broken example:
from mymodule import myfunction
inside a package where the correct import should be:
from app.mymodule import myfunction
Why it fails:
- Python searches for a top-level module named
mymodule - It may not exist on the import path
4. Forgetting package structure
If your code is meant to be a package, organize it like one.
Example:
app/
├── __init__.py
├── main.py
└── mymodule.py
While modern Python supports namespace packages in some cases, beginners usually get more predictable behavior with a clear package layout.
5. Mixing execution styles
A file may appear to work in one environment and fail in another because it is started differently.
For example:
- IDE run button
- terminal command
- test runner
- framework launcher
Always ask: How is this module being executed?
6. Fixing imports by copying files or changing directories randomly
This often hides the real problem instead of solving it. A reliable fix is to:
- choose a package structure
- use consistent imports
- run code from the project root
Comparisons
| Concept | Example | When it works | Main advantage | Main risk |
|---|---|---|---|---|
| Absolute import | from app.mymodule import myfunction | When app is on the import path | Clear and explicit | Can fail if project root is not used correctly |
| Simple top-level import | from mymodule import myfunction | When mymodule is directly discoverable on sys.path | Short syntax | Ambiguous in larger projects |
| Relative import | from .mymodule import myfunction | Only when current file is part of a package | Good for nearby modules | Fails when file is run directly |
Relative vs absolute imports
| Question | Relative import | Absolute import |
|---|---|---|
| Depends on package context? | Yes | Less directly |
| Easy to read in large projects? | Sometimes | Usually yes |
| Safe to run file directly? | No | Sometimes, but not always |
| Good for reusable packages? | Yes, if package is run correctly | Yes |
Direct script run vs module run
| Run style | Example | Package context available? |
|---|---|---|
| Direct script | python app/main.py | Usually no |
| Module execution | python -m app.main | Yes |
Cheat Sheet
# Absolute import
from app.mymodule import myfunction
# Relative import: same package
from .mymodule import myfunction
# Relative import: parent package
from ..utils import helper
Rules to remember
.means "current package"..means "parent package"- Relative imports work only inside a package context
- Running a file directly usually removes that package context
python -m package.modulepreserves package context
Common errors
ImportError: attempted relative import with no known parent package
- You used a relative import in a file Python is treating as a standalone script.
ModuleNotFoundError: No module named 'mymodule'
- Python cannot find
mymoduleon the import path.
SystemError: Parent module '' not loaded, cannot perform relative import
- Python does not know the parent package for a relative import.
Safe habits
- Run code from the project root
- Use
python -m package.modulefor package modules - Prefer clear package structure
- Use absolute imports when clarity matters
- Do not rely on current directory accidents
FAQ
Why does from .mymodule import myfunction fail when I run the file directly?
Because relative imports require Python to know the module's parent package. When you run a file directly, Python usually treats it as a standalone script, not as part of a package.
Why does from mymodule import myfunction sometimes work?
It works when mymodule is available on Python's import path. That can depend on your current working directory, project layout, or environment.
Should I use relative or absolute imports in Python?
Both are valid. Absolute imports are often clearer in larger projects. Relative imports are useful for closely related modules inside a package.
What does python -m app.main do differently?
It runs main as a module inside the app package, so Python keeps package context and relative imports can work.
Do I need __init__.py?
In many beginner-friendly package layouts, yes, it helps make package structure explicit and avoids confusion.
Why does my import work in my IDE but fail in the terminal?
Your IDE may set a different working directory or modify the import path. The terminal may be running the file in a different context.
Can I fix this by changing sys.path manually?
You can, but it is usually not the best solution. It makes code harder to understand and less portable. A proper package structure is usually better.
Mini Project
Description
Build a small Python package with two modules where one module imports a function from the other. This project demonstrates the difference between package-aware execution and direct script execution, which is the root cause of many relative import errors.
Goal
Create a package that prints a greeting by importing a helper function correctly using package-aware imports.
Requirements
- Create a package folder named
app. - Add a module named
helpers.pywith one function that returns a greeting. - Add a module named
main.pythat imports and prints the greeting. - Make the import work using proper package execution.
- Run the program from the project root.
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.